所以這對於所有熟悉程序集的人來說似乎都是一個非常簡單的問題,但是我希望有人能向我解釋下面兩段代碼之間的區別是什麼,假設結果是分段錯誤,另一個沒有,但(對我來說)他們看起來應該是邏輯上相同的。在gcc內聯彙編中加載寄存器? (簡單嗎?)
正常工作:
char *src1; int esi_out, eax;
__asm__
__volatile__(
"lodsb\n\t;"
: "=&S" (esi_out), "=&a" (eax)
: "0" (src1)
);
printf("src1 %c @ %p, esi_out: %x, eax: %x\n", *src1, src1, esi_out, eax);
和打印:
src1 w @ 0x7fffce186959, esi_out: ce18695a, eax: ce186977
所以我的理解是,該代碼應該加載SRC1的值(這是一個地址)ESI,複製值成EAX,將ESI中的地址增加1個字節,然後在退出時將這些值輸出到本地C變量esi_out和eax中。 src1和esi_out看起來是正確的,但eax好像沒有問題。這裏發生了什麼?
代碼的第二位是我們看到的是我不能完全開始應付段錯誤:
__asm__
__volatile__(
"movl %%ebx, %%esi\n\t;"
//"lodsb\n\t;"
: "=&S" (esi_out), "=&b" (ebx), "=&a" (eax)
: "1" (src1)
);
printf("src1 %c @ %p, esi_out: %x, eax: %x, ebx: %x\n",
*src1, src1, esi_out, eax, ebx);
隨着註釋掉LODSB命令,它會產生:
src1 w @ 0x7ffff093b959, esi_out: f093b959, eax: f093b959, ebx: f093b959
並且lodsb命令未被註釋掉,它會發生段錯誤。按照我的思路,直接加載ESI值(如上面的第一種情況),並將其加載到EBX中,然後將它移動到ESI中應該是等效的,不是嗎?
我錯過了什麼?爲什麼寫入EAX的值會顯示出來?我直接將相應的程序寫入程序集,並使用gdb逐步完成,並且工作正常。
任何有識之士將不勝感激。
這確實是一個關於使用64位指針的問題,但只將低32位移入寄存器。謝謝大家。 – fromClouds 2012-01-30 22:17:57