【问题标题】:x86 show the rest of the output (inlining)x86 显示输出的其余部分(内联)
【发布时间】:2017-10-28 15:36:26
【问题描述】:

下面的代码假设显示哪个数字更大或者它们是否相等和总和,但我得到的只是总和,如果我删除第一部分显示的总和部分,显示是否不是数字相等

section .rodata                                                                                                                
          prompt1    db "Enter an integer: ",0   ; 0 is null character                                                                   
          prompt2    db "Enter another integer: ",0                                                                                      
         num_format db "%ld",0                                                                                                          
          format_str1 db "The greater of %ld and %ld is %ld.",10,0  ; 10 is LF                                                           
          format_str2 db "The sum of %ld and %ld is %ld.",10,0  ; 10 is LF                                                               
          equalprompt db "%ld and %ld are equal.",10,0  ; 10 is LF                                                                       

          section .text                                                                                                                  
          global main              ; main and _start are both valid entry points                                                         
          extern printf, scanf     ; these will be linked in from glibc i                                                                

          main:    
          ; prologue                                                                                                                     
          push    rbp          ; save base pointer to the stack                                                                          
          mov     rbp, rsp     ; base pointer = stack pointer                                                                            
          sub     rsp, 16      ; make room for two long integers on the stack                                                            
          push    rbx          ; push callee saved registers onto the stack                                                              
          push    r12          ; push automatically decrements stack pointer                                                             
          push    r13                                                                                                                    
          push    r14                                                                                                                    
          push    r15                                                                                                                    
          pushfq               ; push register flags onto the stack                                                                      

          ; prompt for first integer                                                                                                     
          mov    rdi, dword prompt1    ; double word is 4 bytes; a word is 2 bytes                                                       
                                       ; rdi = 32-bit address of prompt1                                                                 
          xor    rax, rax              ; rax is return value register - zero it out                                                      
          call   printf                ; call the C function from glibc                                                                  

          ; read first integer                                                                                                           
          lea    rsi, [rbp-8]          ; load effective address - this instruction                                                       
                                       ; computes the address 8 bytes above the                                                          
                                       ; base pointer - the integer read by scanf                                                        

          mov    rdi, dword num_format ;                                                                                                 
          xor    rax, rax              ; zero out return value register                                                                  
          call   scanf                 ; call C function                                                                                 
                                      ; scanf reads the input as an integer                                                              

          ; prompt for second integer                                                                                                    
          mov    rdi, dword prompt2                                                                                                      
          xor    rax, rax                                                                                                                
          call   printf                                                                                                                  

          ; read second integer                                                                                                          
          lea    rsi, [rbp-16]                                                                                                           
          mov    rdi, dword num_format                                                                                                   
          xor    rax, rax                                                                                                                
          call   scanf                                                                                                                   

          ; determine if num2 (second integer) is greater than num1 (first integer)                                                      
          xor     rbx, rbx      ; RBX = 0x0                                                                                              
          mov     rax, [rbp-16] ; RAX = num2 ; load rax with value at rdb-16                                                             
          cmp     rax, [rbp-8]  ; compute (num1) - (num2) and set condition codes                                                        
          ; in machine status word register based on result                                                                              
          jl     lessthan      ; jump if num1 <= num2                                                                                    
          je      equal                                                                                                                  

         ; num1 > num2                                                                                                                  
          mov     rdi, dword format_str1                                                                                                 
          mov     rsi, [rbp-8]     ; num1 
          mov     rdx, [rbp-16]    ; num2                                                                                                
          mov     rcx, [rbp-16]    ; greater of the two                                                                                  
         ;mov     rcx, 0                                                                                                                 
          ; add     rcx, rsi                                                                                                             
          ; add     rcx, rdx                                                                                                             
          ; xor     rax, rax                                                                                                             
          jmp sum                                                                                                                        

          lessthan:                                                                                                                      
          ; num1 < num2                                                                                                                  
          mov     rdi, dword format_str1                                                                                                 
          mov     rsi, [rbp-8]   ; num1                                                                                                  
          mov     rdx, [rbp-16]  ; num2                                                                                                  
          mov     rcx, [rbp-8]   ; greater of the two                                                                                    
         ;mov     rcx, 0                                                                                                                 
         ;add     rcx, rsi                                                                                                               
          ;  add     rcx, rdx                                                                                                            
          ;  xor     rax, rax                                                                                                            
         jmp     sum                                                                                                                    

         equal:                                                                                                                         
         mov     rdi, dword equalprompt                                                                                                 
         mov     rsi, [rbp-8]   ; num1                                                                                                  
         mov     rdx, [rbp-16]  ; num2                                                                                                  
         jmp     sum                                                                                                                    

         sum:                                                                                                                           

         mov    rdi, dword num_format ;                                                                                                 
         mov     rdi, dword format_str2                                                                                                 
         mov     rsi, rsi   ; num1                                                                                                      
         mov     rdx, rdx  ; num2                                                                                                       
         mov     rcx, 0                                                                                                                 
         add     rcx, rsi                                                                                                               
         add     rcx, rdx                                                                                                               
         jmp exit                                                                                                                       

         exit:                                                                                                                          
         call    printf                                                                                                                 
         ; epilogue                                                                                                                     
         popfq                                                                                                                          
         pop     r15                                                                                                                    
         pop     r14                                                                                                                    
         pop     r13                                                                                                                    
         pop     r12                                                                                                                    
         pop     rbx                                                                                                                    
         add     rsp, 16        ; set back the stack level                                                                              
         leave                                                                                                                          
         ret    

示例输出如下:

Enter an integer: 7                                                                                                                        
Enter another integer: 3                                                                                                                   
The sum of 7 and 3 is 10 

【问题讨论】:

  • 请删除行号,以便其他用户可以组装您的代码并将其插入调试器。
  • call printf 在第 120 行只能做一个或另一个。我认为您应该在第 109 行添加另一个 call printf
  • 您不需要在函数中保留 FLAGS,它们会像 rcxrdx 等一样被调用破坏。此外,您不需要推送/弹出您从未接触过的寄存器(如r12)。这只是一个浪费的指令,就像jmp exit / exit:。您无需跳过空行;无论如何,执行总是转到下一条指令。

标签: assembly x86 nasm x86-64


【解决方案1】:
mov rax, [rbp-16] ; RAX = num2 ; load rax with value at rdb-6
cmp rax, [rbp-8]  ; compute (num1) - (num2) and set condition code
jl   lessthan      ; jump if num1 <= num2
je   equal

cmp 开头的 cmets 大多是错误的(倒置)!
cmp 计算的是 RAX - [rbp-8],所以 num2 - num1
如果 num2 num1,你的 jl lessthan 会跳转。 幸运的是,在后面的 sn-ps 中填充两者中较大者的代码是正确的。


当代码到达标签 sum 时,您立即开始销毁您精心设置的 RDI 寄存器。您应该首先发出call printf 以显示第一行显示较大数字的结果。此后,您可以设置显示总和的第二行结果。


为什么不简化一下代码?您可以先将 num1 放入 RSI 并将 num2 放入 RDX,然后比较这些寄存器而不是在 RAX 中进行比较,然后必须加载这些重复注册。
如果这样做可以减少程序中的分支数量,也不要害怕做一些看似无用的操作。看看下一个代码如何加载 RDI 并且可能稍后必须用另一个值重新加载它?加载 RCX 也是一样,可能需要重新加载。

    mov     rsi, [rbp-8]  ; num1 
    mov     rdx, [rbp-16] ; num2             
    cmp     rsi, rdx
    mov     rdi, dword equalprompt                            
    je      sum
    mov     rdi, dword format_str1                            
    mov     rcx, rsi      ; num1 is greater of the two
    jg      sum           ; jump if num1 > num2        
    mov     rcx, rdx      ; num2 is greater of the two      
sum:
    call    printf
mov     rcx, 0
add     rcx, rsi

这样做没有意义。只需将mov 的第一个数字使用mov rcx, rsi 转换为RCX

    mov     rdi, dword format_str2
    mov     rcx, rsi
    add     rcx, rdx
    call    printf

【讨论】:

    猜你喜欢
    • 2016-01-24
    • 2021-01-11
    • 2014-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 1970-01-01
    相关资源
    最近更新 更多