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]

В остальном, вроде бы, без изменений (я имею в виду - при портировании :)