Если не знаешь 32-битных регистров, можешь пользоваться 16-битными, главное помнить:
1) указатели как были, так и остались 32-хбитными, только вместо сегмента - старшие 16 бит смещения (указатели стали ближними!); сегментные регистры не используются (в смысле - не изменяются), используется модель памяти flat (тот же tiny, только больше :);
2) НЕ ТРОГАЙ СЕГМЕНТНЫЕ РЕГИСТРЫ! просто имей в виду, что DS=ES=FS=GS=SS;
3) на вершину стека указывает не 16-тибитный SP, а 32-битный ESP;
4) где раньше неявно использовались 16-битные регистры (SI/DI/CX в строковых операциях, CX в LOOP-е, BX в XLAT, BP/SP в LEAVE и т. п.), теперь используются 32-битные, например: { записать ярко-зеленый восклицательный знак по указанному адресу в видеобуфере }
{ 16 bit } procedure PutExcl(where: pointer); assembler; asm les di,where { ES:DI } mov ax,0A21h stosw end;
{ 32 bit } procedure PutExcl(where: pointer); assembler; asm mov edi,where { EDI } mov ax,0A21h stosw end;
5) вместо PUSHF/POPF, PUSHA/POPA следует использовать PUSHFD/POPFD, PUSHAD/POPAD чтобы класть в стек или снимать с него 32-хбитные регистры; также следует использовать RETFD/IRETD вместо RETF/IRET, но эти команды теперь не требуются;
6) кстати, на всякий случай: дальние процедуры/функции не используются, теперь они все - ближние!
7) и самое главное, на всякий случай: если не вполне понимаешь, что делает программа - НЕ ПОРТИРУЙ ЕЕ! (впрочем, это очевидно :)
Но этот способ портирования неэффективен, некрасив и неинтересен. Лучше пойти другим путем - переписать код в 32-хбитных инструкциях. Следует помнить следующее:
8) к 16-тибитным регистрам общего назначения (и к IP и FLAGS) добавилось 16 бит сверху и буковка «E» слева :), т. е. получились EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, EIP, EFLAGS. При этом 16-разрядные «предки» стали неотъемлемой частью 32-хбитных «потомков», пример:
xor eax,eax { EAX := 0 } mov ax,0ABCDh { EAX := 0000ABCDh } shl eax,4 { EAX := 000ABCD0h } sar ax,4 { EAX := 000AFBCDh } rol ah,4 { EAX := 000ABFCDh }
9) все команды работают с 32-битными операндами так же, как и с 16-тибитными, нужно только подставить везде буковку «E» и заменить word на dword; я имею в виду следующее:
{ 16 bit } cwd { DX:AX := AX (signed) } mov bx,some_var { word ptr } idiv bx { AX := DX:AX div BX } { DX := DX:AX mod BX }
переделываешь в
{ 32 bit } cdq { EDX:EAX := EAX (signed) } mov ebx,some_var{ dword ptr } idiv ebx { EAX := EDX:EAX div EBX } { EDX := EDX:EAX mod EBX }
10) команды PUSHxx/POPxx теперь работают с двойными словами (и вообще, везде, где раньше было слово - теперь два :)
11) появились весьма полезные 32-хбитные команды, вот некоторые из них: CWDE: EAX := AX (со знаком) CQD: EDX:EAX := EAX (со знаком)
32-битные строковые операции: LODSD, STOSD, SCASD, CMPSD, MOVSD, INSD, OUTSD, используется EAX вместо AX, ESI/EDI +-= 4; REP/REPE/REPZ/REPNE/REPNZ используют ECX вместо CX
список далеко :) не полный, если хочешь узнать больше - RTFM :)
12) адресация: теперь смещения могут быть размером в 1 или 4 байта; можно использовать любые 32-хбитные регистры общего назначения (до двух регистров); один из используемых регистров (кроме ESP) можно умножать (без последствий :) на 2, 4 или 8, например:
mov eax,PointerList[edx + eax*4]
В остальном, вроде бы, без изменений (я имею в виду - при портировании :)