我刚刚开始与NASM组装商进行组装。使用C驱动程序使用gcc进行编译。据我所知,可以很容易地以两种方式实现模函数(假设size_t a
中的eax
,size_t b
中的ebx
for { {1}}):
第一个选项:
mod(a, b)
第二个选项:
minus:
sub eax, ebx
modulo:
CMP eax, ebx
JGE minus
leave ; else result is already saved in eax
ret
以下是必需的文件:
diver.c:
modulo: ; calcs eax mod ebx, returns eax
mov edx, 0 ; clear higher 32-bits as edx:eax / ebx is calced
div ebx
mov eax, edx ; the remainder was stored in edx
leave
ret
modulo.asm:
#include "cdecl.h"
#include "stdio.h"
int PRE_CDECL asm_main( size_t, size_t ) POST_CDECL;
int main() {
size_t a;
size_t b;
int result;
a = 15;
b = 5;
result = asm_main(a, b);
printf("%d", result);
return 0;
}
编译正常:
segment .data
buffer: times 1 dd 0 ; define a 32-bit buffer
segment.text
global asm_main
modulo:
; one of above options implemented here
asm_main:
enter 0, 0
push ebp
mov ebp, esp ; save the stack pointer on ebp
pusha
; dump_regs 0 ,requires %include "asm_io.inc"
mov eax, [ebp + 12] ; move first argument to eax
mov ebx, [ebp + 16] ; move second argument to ebx
; dump_regs 1
call modulo ; result is saved in eax now
; dump_regs 2
mov ecx, buffer ; get buffer's address into the register
mov [ecx], eax ; save the modulo result into the buffer
popa
pop ebp
mov eax, [buffer] ; move the saved result back into eax
leave
ret
使用两个选项执行时,都会以某种方式收到分段错误:
$ nasm -f elf modulo.asm
$ gcc -m32 -c driver.c
$ gcc -m32 -o modulo driver.o modulo.o
我不知道在哪里可以尝试访问环境外部的地址,因此我仍无法弄清错误在哪里。
如果有人可以帮助我找到麻烦制造者或建议我在Assembler中使用有效的模函数(如果可能,最好使用intel语法),我将不胜感激。谢谢!
PS:this link中可以找到$ ./modulo
Register Dump # 0
EAX = 00000001 EBX = F76D0000 ECX = FFF987F0 EDX = FFF98814
ESI = 00000000 EDI = 00000000 EBP = FFF987A4 ESP = FFF98784
EIP = 080484EE FLAGS = 0296 SF AF PF
Register Dump # 1
EAX = 0000000F EBX = 00000005 ECX = FFF987F0 EDX = FFF98814
ESI = 00000000 EDI = 00000000 EBP = FFF987A4 ESP = FFF98784
EIP = 080484FB FLAGS = 0296 SF AF PF
Segmentation fault
,asm_io.asm
和asm_io.inc
。
答案 0 :(得分:0)
谢谢@fuz,@harold的评论。我想您的评论实际上可以成为答案:)
更改第二个选项
modulo: ; calcs eax mod ebx, returns eax
mov edx, 0 ; clear higher 32-bits as edx:eax / ebx is calced
div ebx
mov eax, edx ; the remainder was stored in edx
ret
解决了整个问题。
警告:即使删除leave
,第一个选项也会返回错误的值。
附录:
正如彼得·科德斯(Peter Cordes)所说,使用asm_main
实际上不是一个好习惯。所以我修改了C约定中的两个选项,如下所示:
第一个选项:
modulo: ; Function size_t modulo(a, b)
mov eax, dword [esp+4H] ; a in EAX
mov edx, dword [esp+8H] ; b in EDX
cmp eax, edx ; if (a < b) -> return
JL return
minus: sub eax, edx ; else: a = a-b
cmp eax, edx ; if (a >= b) -> minus
JGE minus
return: ; else: return
ret
第二个选项:
modulo:
mov eax, dword [esp+4H] ; a in EAX
mov edx, 0 ; EDX should be zero
div dword [esp+8H] ; a / b
mov eax, edx ; move a % b to eax
ret
modulo.asm :
global modulo
segment .text
modulo: ; insert one of the options above here
modulodriver.c :
#include "cdecl.h"
#include "stdio.h"
unsigned int PRE_CDECL modulo( unsigned int, unsigned int ) POST_CDECL;
int main() {
unsigned int a = 25;
unsigned int b = 5;
unsigned int result = modulo(a, b);
printf("%d", result);
return 0;
}
我已经测试了两个选项,并且工作正常:)
注意:如果使用-m32
选项进行编译,则可以使用size_t
代替unsigned int
,但是size_t
将是64位整数,大于不过,在64位系统上使用的寄存器。