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
,这将期望找到它的fir
rdi
中的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
,这将期望找到它的fir
rdi
中的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的函数)时