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