Assembly 了解汇编、nasm和x86中的printf函数。我不知道';我不知道为什么这个代码是';不要打印任何东西 位64; 全球主要 外部打印 第节.案文 主要:;这是由C库启动代码调用的 推动rbx;需要使printf 16字节对齐。 ; 现在我们只做一次! 推qword 300 催缴股款 mov-rdi,dfmt;设置第一个参数(格式) mov-rsi,rax;设置第二个参数(低字节) xor-rax,rax;因为printf是varargs,我们必须清除rax 调用printf;printf(格式、当前编号) pop-rbx;必须为Linux恢复rbx ret;从main返回到C库包装器 总数: 推动rbp;检索参数 推动rbx;保存以前的 mov rbp,rsp 加上rsp,24;为integer创建空间 mov-rbx,[rbp];rbx=参数 cmp-rbx,0;如果(n
让我们一点一点地看一下 在Assembly 了解汇编、nasm和x86中的printf函数。我不知道';我不知道为什么这个代码是';不要打印任何东西 位64; 全球主要 外部打印 第节.案文 主要:;这是由C库启动代码调用的 推动rbx;需要使printf 16字节对齐。 ; 现在我们只做一次! 推qword 300 催缴股款 mov-rdi,dfmt;设置第一个参数(格式) mov-rsi,rax;设置第二个参数(低字节) xor-rax,rax;因为printf是varargs,我们必须清除rax 调用printf;printf(格式、当前编号) pop-rbx;必须为Linux恢复rbx ret;从main返回到C库包装器 总数: 推动rbp;检索参数 推动rbx;保存以前的 mov rbp,rsp 加上rsp,24;为integer创建空间 mov-rbx,[rbp];rbx=参数 cmp-rbx,0;如果(n,assembly,x86-64,nasm,Assembly,X86 64,Nasm,让我们一点一点地看一下 在main函数中,您有push qword 300。我假设这是为了将一个参数传递给sum?如果是这样……那不是您要做的。我建议您遵循AMD64调用约定,使用mov rdi,300,然后使用调用sum,这将期望找到它的firrdi中的st参数 在任何情况下,在sum中,您首先要做的是push rbp,这是非常标准的。然后您push rbx。这是一个被调用方保存的寄存器,非常好。然后mov rbp,rsp,这也是非常标准的 现在,您可以使用add rsp,24释放一些堆栈,我
main
函数中,您有push qword 300
。我假设这是为了将一个参数传递给sum
?如果是这样……那不是您要做的。我建议您遵循AMD64调用约定,使用mov rdi,300
,然后使用调用sum
,这将期望找到它的firrdi
中的st参数
在任何情况下,在sum
中,您首先要做的是push rbp
,这是非常标准的。然后您push rbx
。这是一个被调用方保存的寄存器,非常好。然后mov rbp,rsp
,这也是非常标准的
现在,您可以使用add rsp,24
释放一些堆栈,我不明白。堆栈向较低的地址增长,因此要保留一些堆栈,您可以从rsp
中减去。但可能这不是您正在做的事情
现在它真的让我感到困惑。你确实是mov rbx,[rbp]
,但是由于rbp
没有被main
函数修改,它不会指向我们想要的任何地方。我只能假设这是试图在堆栈上获取参数的一种尝试
老实说,在这一点上,我被难住了
通常使用以下样板文件启动函数
BITS 64;
global main
extern printf
section .text
main: ; This is called by the C library startup code
push rbx ; required to make printf 16-byte aligned.
; For now we only do this once!
push qword 300
call sum
mov rdi, dfmt ; set 1st parameter (format)
mov rsi, rax ; set 2nd parameter (low byte)
xor rax, rax ; because printf is varargs we must clear rax
call printf ; printf(format, current_number)
pop rbx ; must restore rbx for Linux
ret ; Return from main back into C library wrapper
sum:
push rbp ; retrieve parameter
push rbx ; save previous
mov rbp, rsp
add rsp, 24 ; create room for integer
mov rbx, [rbp] ; rbx = param
cmp rbx, 0 ; if (n <= 0)
je base
dec rbx ; decrement rbx to place in stack
push rbx ; put (rbx - 1) in stack
inc rbx
call sum ; calculate sum(n - 1)
add rax, rbx
pop rbx
jmp end
base:
mov rax, 1
end:
pop rbx
pop rbp
ret
dfmt:
db "%ld", 10, 0
push rbp
mov rbp, rsp
原因是为了保护堆栈。现在可以对rbp
执行所有引用,它在代码中永远不会更改(始终指向堆栈帧)。它是被调用方保存的寄存器,因此我们必须保存它,并在设置它之前在堆栈上执行此操作
通常使用以下样板文件结束函数
BITS 64;
global main
extern printf
section .text
main: ; This is called by the C library startup code
push rbx ; required to make printf 16-byte aligned.
; For now we only do this once!
push qword 300
call sum
mov rdi, dfmt ; set 1st parameter (format)
mov rsi, rax ; set 2nd parameter (low byte)
xor rax, rax ; because printf is varargs we must clear rax
call printf ; printf(format, current_number)
pop rbx ; must restore rbx for Linux
ret ; Return from main back into C library wrapper
sum:
push rbp ; retrieve parameter
push rbx ; save previous
mov rbp, rsp
add rsp, 24 ; create room for integer
mov rbx, [rbp] ; rbx = param
cmp rbx, 0 ; if (n <= 0)
je base
dec rbx ; decrement rbx to place in stack
push rbx ; put (rbx - 1) in stack
inc rbx
call sum ; calculate sum(n - 1)
add rax, rbx
pop rbx
jmp end
base:
mov rax, 1
end:
pop rbx
pop rbp
ret
dfmt:
db "%ld", 10, 0
push rbp
mov rbp, rsp
这将按照AMD64调用约定的要求,将堆栈指针和rbp
恢复到它们在条目上的状态。这有一个同义词:leave
。以下代码是等效的
mov rsp, rbp
pop rbp
ret
现在,当您使用printf
(或任何可能使用xmm
寄存器的函数)时,您还必须确保在调用前堆栈在16字节边界上对齐。您可以假设堆栈在进入main
时对齐。push rbp
会将其弄乱(关8),但当您执行调用printf
时,您将再推8个字节(返回地址),并且presto!堆栈将对齐
我的最后一个建议是使用AMD64调用约定,而不是使用堆栈。将参数放入rdi
,并在rax
中获取返回值
如果不知道您想做什么,我就无法提供更多的帮助。让我们一点一点地看一下 在
main
函数中,您有push qword 300
。我假设这是为了将一个参数传递给sum
?如果是这样……那不是您要做的。我建议您遵循AMD64调用约定,使用mov rdi,300
,然后使用调用sum
,这将期望找到它的firrdi
中的st参数
在任何情况下,在sum
中,您首先要做的是push rbp
,这是非常标准的。然后您push rbx
。这是一个被调用方保存的寄存器,非常好。然后mov rbp,rsp
,这也是非常标准的
现在,您可以使用add rsp,24
释放一些堆栈,我不明白。堆栈向较低的地址增长,因此要保留一些堆栈,您可以从rsp
中减去。但可能这不是您正在做的事情
现在它真的让我感到困惑。你确实是mov rbx,[rbp]
,但是由于rbp
没有被main
函数修改,它不会指向我们想要的任何地方。我只能假设这是试图在堆栈上获取参数的一种尝试
老实说,在这一点上,我被难住了
通常使用以下样板文件启动函数
BITS 64;
global main
extern printf
section .text
main: ; This is called by the C library startup code
push rbx ; required to make printf 16-byte aligned.
; For now we only do this once!
push qword 300
call sum
mov rdi, dfmt ; set 1st parameter (format)
mov rsi, rax ; set 2nd parameter (low byte)
xor rax, rax ; because printf is varargs we must clear rax
call printf ; printf(format, current_number)
pop rbx ; must restore rbx for Linux
ret ; Return from main back into C library wrapper
sum:
push rbp ; retrieve parameter
push rbx ; save previous
mov rbp, rsp
add rsp, 24 ; create room for integer
mov rbx, [rbp] ; rbx = param
cmp rbx, 0 ; if (n <= 0)
je base
dec rbx ; decrement rbx to place in stack
push rbx ; put (rbx - 1) in stack
inc rbx
call sum ; calculate sum(n - 1)
add rax, rbx
pop rbx
jmp end
base:
mov rax, 1
end:
pop rbx
pop rbp
ret
dfmt:
db "%ld", 10, 0
push rbp
mov rbp, rsp
原因是为了保护堆栈。现在可以对rbp
执行所有引用,它在代码中永远不会更改(始终指向堆栈帧)。它是被调用方保存的寄存器,因此我们必须保存它,并在设置它之前在堆栈上执行此操作
通常使用以下样板文件结束函数
BITS 64;
global main
extern printf
section .text
main: ; This is called by the C library startup code
push rbx ; required to make printf 16-byte aligned.
; For now we only do this once!
push qword 300
call sum
mov rdi, dfmt ; set 1st parameter (format)
mov rsi, rax ; set 2nd parameter (low byte)
xor rax, rax ; because printf is varargs we must clear rax
call printf ; printf(format, current_number)
pop rbx ; must restore rbx for Linux
ret ; Return from main back into C library wrapper
sum:
push rbp ; retrieve parameter
push rbx ; save previous
mov rbp, rsp
add rsp, 24 ; create room for integer
mov rbx, [rbp] ; rbx = param
cmp rbx, 0 ; if (n <= 0)
je base
dec rbx ; decrement rbx to place in stack
push rbx ; put (rbx - 1) in stack
inc rbx
call sum ; calculate sum(n - 1)
add rax, rbx
pop rbx
jmp end
base:
mov rax, 1
end:
pop rbx
pop rbp
ret
dfmt:
db "%ld", 10, 0
push rbp
mov rbp, rsp
这将按照AMD64调用约定的要求,将堆栈指针和rbp
恢复到它们在条目上的状态。这有一个同义词:leave
。以下代码是等效的
mov rsp, rbp
pop rbp
ret
现在,当您使用printf
(或任何可能使用xmm
r的函数)时