2017-10-28 206 views
1

下面的代碼假設有顯示如果哪個數字更大或者它們是否相等和總和,但我得到的只是總和,如果我刪除了總和部的第一部分,其中顯示的數字是否等於x86顯示輸出的其餘部分(內聯)

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 
+0

請刪除行號,以便其他用戶可以組裝您的代碼並將其插入調試器。 – fuz

+1

線路120上的'call printf'只能執行一個或另一個。我認爲你應該在第109行添加另一個'call printf'。 –

+0

你不需要在函數中保存FLAGS,它們像'rcx','rdx'等一樣被調用。此外,你不需要推動/彈出你永遠不會碰到的寄存器(比如'r12')。這只是一個浪費的指令,就像'jmp exit' /'exit:'一樣。你不需要跳過空行;反正總是執行下一條指令。 –

回答

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開始的評論大多是錯誤的(反向)!
什麼cmp計算是RAX - [rbp-8],所以num2 - num1
您的jl lessthan跳轉如果num2 < num1。 幸運的是,在後面的代碼片段中填充兩者中較大者的代碼是正確的。


當代碼到達標籤總和,你立即摧毀你精心設置了RDI寄存器開始。您應該首先發出call printf以顯示顯示較大數字的第一行結果。此後,您可以設置顯示總和的第二行結果。


爲什麼不簡化代碼呢?您可以從num1中的RSInum2中的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第一個號碼變成RCX使用mov rcx, rsi

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