====== 32-битный ассемблер ======
Если не знаешь 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]
В остальном, вроде бы, без изменений (я имею в виду - при портировании :)