Как использовать “GS”: в 64-разрядном Windows Assembly (например, портируя код TLS)

function getMoney(A){
    var a = new Number(A);
    var b = a.toFixed(2); //get 12345678.90
    a = parseInt(a); // get 12345678
    b = (b-a).toPrecision(2); //get 0.90
    b = parseFloat(b).toFixed(2); //in case we get 0.0, we pad it out to 0.00
    a = a.toLocaleString();//put in commas - IE also puts in .00, so we'll get 12,345,678.00
    //if IE (our number ends in .00)
    if(a < 1 && a.lastIndexOf('.00') == (a.length - 3))
    {
        a=a.substr(0, a.length-3); //delete the .00
    }
    return a+b.substr(1);//remove the 0 from b, then return a + b = 12,345,678.90
}
alert(getMoney(12345678.9));

Это работает в FF и IE

10
задан Mgetz 1 May 2015 в 15:44
поделиться

6 ответов

Вы можете изменить контекст потока напрямую через API SetThreadcontext . Однако вам нужно убедиться, что поток не запущен, пока контекст изменяется. Либо приостанавливает его и изменяет контекст из другого потока, либо инициирует ложное исключение SEH и изменяет контекст потока в обработчике SEH. Затем ОС изменит контекст потока для вас и перепланировит поток.

Обновление:

Пример кода для второго подхода:

__try
{
    __asm int 3 // trigger fake exception
}
__except(filter(GetExceptionCode(), GetExceptionInformation()))
{
}

int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
    ep->ContextRecord->SegGs = 23;
    ep->ContextRecord->Eip++;
    return EXCEPTION_CONTINUE_EXECUTION;
}

Инструкция в блоке try в основном вызывает программную исключительную ситуацию. Затем ОС передает управление процедуре фильтрации, которая изменяет контекст потока, It's kind of a hack, but its all documented functionality :)

4
ответ дан 4 December 2019 в 01:31
поделиться

Почему вам нужно установить регистр GS? Windows устанавливает, если для вас, чтобы указать на пространство TLS.

Хотя я не кодировал для X64, я построил компилятор, который генерирует битовый код X32, который управляет потоками, используя FS. В X64 GS заменяет FS, а все остальное работает примерно так же . Итак, GS указывает на локальное хранилище потока. Если вы выделили блок локальных переменных потока (в Win32 мы выделяем 32 из 64 по смещению 0), ваш поток теперь имеет прямой доступ к 32 ячейкам хранения для всего, что он хочет делать. Вам не нужно выделять рабочее пространство для конкретного потока; Windows сделала это за вас.

Конечно, вы можете захотеть скопировать то, что вы считаете своими данными конкретного потока, в это пространство, которое вы отложили, в любом планировщике, который вы '

2
ответ дан 4 December 2019 в 01:31
поделиться

Haven't ever modified GS in x64 code, so I may be wrong, but shouldn't you be able to modify GS by PUSH/POP or by LGS?

Update: Intel manuals say also mov SegReg, Reg is permissible in 64-bit mode.

1
ответ дан 4 December 2019 в 01:31
поделиться

Поскольку x86_64 имеет намного больше регистров, чем x86, вам может понадобиться один вариант рассмотреть, если вы не можете использовать GS, было бы просто использовать один из регистров общего назначения (например, EBP) в качестве базового указателя и компенсировать разницу с помощью новых регистров R8-R15.

1
ответ дан 4 December 2019 в 01:31
поделиться

Что произойдет, если вы просто перейдете к потокам ОС? Неужели так плоха производительность?

Вы можете использовать один слот TLS размером с указатель для хранения основы области хранения вашего легкого потока. Вам просто нужно будет поменять местами один указатель во время переключения контекста. Загружайте оттуда один из новых временных регистров всякий раз, когда вам нужно значение, и вам не нужно беспокоиться об использовании одного из немногих, сохраняемых при вызовах функций.

Другое поддерживаемое решение - использовать Fiber API. , чтобы запланировать легкие потоки. Затем вы должны изменить JIT, чтобы выполнять правильные вызовы к FlsGet / SetValue .

Извините, похоже, что старый код написан, чтобы полагаться на префиксы сегментов для адресации, и теперь LDT просто недоступен для Что-то в этом роде. Вы' третий срок. Я думаю, что могу использовать "lea", за которым следует форма с двумя регистрами

Звучит как хороший план.

случаи, такие как "mov eax, mem", которые принимают префикс, но их нужно полностью заменить для использования на основе регистров адресация

Возможно, вы могли бы переместить их на адресацию адрес + смещение. Регистр смещения может быть регистром, содержащим базу вашего блока TLS.

1
ответ дан 4 December 2019 в 01:31
поделиться

Почему бы не использовать GetFiberData или вы пытаетесь избежать двух дополнительных инструкций?

1
ответ дан 4 December 2019 в 01:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: