2014-10-31 28 views
0

我想在64位程序集中編寫一個函數(最大值),我不知道我在做什麼錯誤,也許你們有些人可以確定我做錯了什麼:/在64位程序集中編寫函數

這裏的功能:

int max(int a, int b) { 
/* Return the larger of the two integers `a' and `b'. */ 
if (a > b) 
return a; 
else 
return b; 
} 

這裏是我的彙編代碼(帶註釋):

push %rbp 
    mov %rsp, %rbp 
    mov %rdi, %rax 
    mov %rsi, %rcx 
    test %rax, %rax    // Checking if first parameter is signed 
    js .signedRAX 
    test %rcx, %rcx    // Checking if second parameter is signed 
    js .signedRCX 
    jmp .compare     // If either one signed then jump to .compare 
    .signedRAX: 
    test %rcx, %rcx    // Checking if both are signed 
    js .signedRAXandRCX 
    mov %rcx, %rax     // If not then return the positive number 
    jmp .end      // finish the function 
    .signedRCX: 
    jmp .end      // If only the second parameter is signed then jump 
    .signedRAXandRCX:    // straight to end of function and return %rax 
    cmp %rax, %rcx     // If both are signed compare which one is the max 
    jl .end 
    mov %rcx, %rax 
    jmp .end 
    .compare: 
    cmp %rax, %rcx     // If both are positive then compare which one is 
    jg .end      // the max 
    mov %rcx, %rax 
    .end: 
    mov %rbp, %rsp 
    pop %rbp 
    ret 

比較兩個參數都登錄,然後都當我得到了錯誤的輸出正。

+1

只是'子a,b'和測試結果使用'jg','jge','jl'。就這樣。 – alexander 2014-10-31 10:09:41

+0

所以我可以跳過所有的跳轉來檢查簽名? – drleifz 2014-10-31 10:11:12

+0

@drleifz這正是'jg' /'jl'測試和'ja' /'jb'測試之間的區別:後者對無符號數有效。 – glglgl 2014-10-31 10:14:47

回答

2

你的工作太複雜了。

如果我輸入你的程序gcc -S,我得到

max: 
.LFB0: 
     .cfi_startproc 
     pushl %ebp 
     .cfi_def_cfa_offset 8 
     .cfi_offset 5, -8 
     movl %esp, %ebp 
     .cfi_def_cfa_register 5 
     movl 8(%ebp), %eax 
     cmpl 12(%ebp), %eax 
     jle  .L2 
     movl 8(%ebp), %eax 
     jmp  .L3 
.L2: 
     movl 12(%ebp), %eax 
.L3: 
     popl %ebp 
     .cfi_restore 5 
     .cfi_def_cfa 4, 4 
     ret 
     .cfi_endproc 
.LFE0: 

如果我接替你的 「ABI」 和傳遞參數的方式,

我得到

max: 
    push %rbp 
    mov %rsp, %rbp 
    mov %rdi, %rax 
    mov %rsi, %rcx 
    cmpl %rcx, %rax 
    jle .L2 
    movl %rcx, %rax 
.L2: 
    mov %rbp, %rsp 
    pop %rbp 
    ret 
+0

我首先嚐試了這個簡化版本,但在處理帶符號整數時得到了不同的輸出結果。所以這就是爲什麼我嘗試所有這些測試來比較簽名整數。 – drleifz 2014-10-31 10:18:00

0

這裏來自問題的ASM的等效C僞代碼。你可以看到,對於a >= 0b < 0它返回b。對於a < 0b >= 0它返回a。這是不正確的。代碼中可能存在其他錯誤,因爲如此簡單的操作編碼確實很麻煩。代碼中很難看到任何東西。不要讓簡單的事情如此複雜。遵循KISS原則。

// test %rax, %rax 
// js .signedRAX 
if (a >= 0) { 
    // test %rcx, %rcx 
    // js .signedRCX 
    if (b >= 0) { 
     // .compare 
     // cmp %rax, %rcx     // If both are positive then compare which one is 
     // jg .end      // the max 
     if (a > b) { 
      b = a; 
     } 
     return b; 
    } else { 
     // .signedRCX 
     return b; 
    } 
} else { 
    // .signedRAX 
    // test %rcx, %rcx    // Checking if both are signed 
    // js .signedRAXandRCX 
    if (b >= 0) { 
     b = a; 
     return b; 
    } else { 
     // .signedRAXandRCX 
     // cmp %rax, %rcx     // If both are signed compare which one is the max 
     // jl .end 
     if (a < b) { 
      b = a; 
     } 
     return b; 
    } 
} 
+0

當你把它放在這裏..它看起來非常混亂:/ – drleifz 2014-10-31 13:14:28

相關問題