我正在嘗試編寫一個將調用匯編函數來反轉字符串的c程序。但是,我很難獲取彙編代碼來遍歷字符串來查找結尾字符「0」。在C中調用匯編函數,反轉字符串
我的C代碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// These functions will be implemented in assembly:
//
void strrev(char *str) ;
int main(){
char *str1;
str1 = strdup("Hello World");
strrev(str1);
printf("str1 reversed: \"%s\"\n", str1) ;
free(str1);
return 0;
}
任何我的彙編代碼很簡單:
; File: strrev.asm
; A subroutine called from C programs.
; Parameters: string A
; Result: String is reversed and returned.
SECTION .text
global strrev
_strrev: nop
strrev:
push ebp
mov ebp, esp
; registers ebx,esi, and edi must be saved if used
push ebx
push edi
xor esi, esi
xor eax, eax
lea ecx, [esp+8] ; load the start of the array into ecx
jecxz end ; jump if [ecx] is zero
mov edi, ecx
reverseLoop:
cmp byte[edi], 0
je end
inc edi
inc eax
jmp reverseLoop
end:
pop edi ; restore registers
pop ebx
mov esp, ebp ; take down stack frame
pop ebp
ret
所有我想這個代碼,現在所要做的只是通過串迭代,直到它找到在reverseLoop內部結束。但是,如果我嘗試使用gdb並逐步執行程序,則在查看第一個字符「H」後,它似乎立即失敗。
運行與GDB與線25斷裂,同時顯示與「顯示/ C $ EDI」的EDI寄存器產生以下輸出:
(gdb)
reverseLoop() at strrev.asm:25
25 cmp byte[edi], 0
1: /c $edi = 72 'H'
哪個是正確的,但如果我通過下臺到INC edi,edi立即變得不正確。它應該是「E」,因爲「Hello World」中的第二個字符是「e」。但是,gdb的輸出列出其爲「I」:
27 inc edi
1: /c $edi = 72 'H'
(gdb)
28 inc eax
1: /c $edi = 73 'I'
難道我做錯了什麼,當我通過EDI註冊迭代?
順便說一句,這是一個32位或64位系統上?如果它是一個64位系統,則刪除地址的前32位,使指針指向內存中完全不同的地方。 – 2013-05-06 12:14:25
第一個參數是[ebp + 8] NOT [esp + 8]。你也應該使用LEA的MOV instea,否則''((char *)$ ebp + 8)'而不是'(*(char **)($ ebp + 8))''。看看我的回答 – scottt 2013-05-06 12:36:58