В вашем коде есть несколько ошибок.
Строка fmt
определена с dq
, который определяет группы QWORD (64-битные элементы). Это имеет эффект заполнения (с нулевыми байтами) каждой строки, кратной 8 байтам.
В этом случае вы потеряете символ новой строки.
Вместо этого используйте db
.
Это также лучше следовать соглашению с прямым порядком байтов и хранить старшую часть числа в старших адресах.
edx
- старшая часть результата, сохранять ее в [result + 4]
и хранить eax
(нижняя часть ) в [result]
.
Это позволяет другим программистам рассуждать о вашем коде. При той же длине вы также можете использовать xor edx, edx
для установки edx
на ноль .
Наконец, печатная часть.
Прежде всего, правильная строка формата %llx
, поскольку модель, используемая основными компиляторами в 32-битном режиме, - LL64 (т. Е. long
по-прежнему 32 бита, а long long
- 64 бита).
ABI говорит, что вы должны передать long long
аргументов в стеке и их выравнивание составляет 4 байта (что означает, что не нужно добавлять какие-либо отступы).
Кроме того, ABI требует , что стек должен быть выровнен по 16-байтовой границе непосредственно перед инструкцией call
, но, к счастью, использование трех нажатий - это то, что необходимо для его выравнивания в любом случае. Поскольку x86 - это машины с прямым порядком байтов, это можно сделать с помощью:
push DWORD [result+4]
push DWORD [result]
push fmt1
call printf
add esp, 10h
Весь код:
SECTION .data
fmt1: db "%llx", 10, 0
result: dd 0, 0
SECTION .text
EXTERN printf
assFunc:
mov edx,0
mov eax, 0xFFFFFFFF
add eax, 0xFFFFFFFF
adc edx,0
mov [result],eax
mov [result+4],edx
push DWORD [result+4]
push DWORD [result]
push fmt1
call printf
add esp, 0ch
ret
Обратите внимание, что вам на самом деле не нужно сохранять результат в result
переменная, вы можете
push edx
push eax
напрямую, вместо
push DWORD [result+4]
push DWORD [result]