我想在這裏學習一些程序集,我需要來自專業人士的一點幫助!Noob ASM問題
test.s:
.data
helloworld:
.asciz "printf test! %i\n"
.text
.globl main
main:
push $0x40
push $helloworld
call printf
mov $0, %eax
ret
test.working.s:
.data
helloworld:
.asciz "printf test! %i\n"
.text
.globl main
main:
mov $0x40, %esi
mov $printf_test, %edi
mov $0x0, %eax
call printf
mov $0, %eax
ret
compile.sh:
rm test
gcc test.s -o test -lc
chmod 777 test
./test
test.s立即出現segfaults。我通過使用eclipse中的反彙編窗口來製作test.working.s,並且只是編寫一個小的C程序來使用printf打印一些東西。
所以,問題!
爲什麼
test.s
不行在我的C程序,主要是指主(INT ARGC,字符** argv的),是不是?因此,如果我不需要這些參數,我不應該在開始時兩次需要
pop
?在x86-64中,我讀到%rax是64位寄存器,%eax是32位寄存器,%ax是16位寄存器。所以寄存器看起來是這樣的:
XX XX EE EE RR RR RR RR
(R = 4位RAX,E = 4位EAX,X = 4位AX) 在小端系統上(1表示爲0x01000000,我想... )?GCC不會讓我輸入
pop %eax
或push %eax
。它只會讓我輸入64位版本或16位版本。那麼我如何將RAX的32個EAX位推入堆棧呢?我怎麼彈出只有32位?test.working.s(我想這是回答1,但如果不是...)通過更改寄存器來調用printf,而不是將東西壓入堆棧。我認爲這是因爲它更快?你怎麼知道什麼時候調用c函數,按照什麼順序來做到這一點?
這也適用於Windows x86-64嗎?我知道printf的操作可能會有所不同,但如果我在printf後清理並恢復寄存器,我應該沒問題?
你應該如何清理和恢復寄存器?根據http://www.cs.uaf.edu/2005/fall/cs301/support/x86/,它說我「必須保存%esp,%ebp,%esi,%edi」。這是指這樣一個事實,即當我編寫函數時,這些寄存器必須以它們進入的方式返回,或者在我調用某個函數之前我應該自己保存它們。這可能是前者,因爲%esp,但只是檢查!
很明顯,我不會需要x86-64,特別是因爲我剛剛開始,所以如何才能改變x86的compile.sh?
.asciz
只是表示.ascii
+"\0"
?我可以返回駐留在堆棧中的大型結構(> 64位)。這在裝配中如何實現?
乾杯的任何幫助!
非常感謝!任何關於10的想法?另外,如果little endian指示最低有效位位於第一個字節中,您確定它不是'01 00 00 00'嗎?維基百科表示,大字節表示最低有效位位於最後一個字節 – AStupidNoob 2013-05-14 06:25:43
這取決於您如何查看數據。如果你在一個文件中有32位小端值1,2,並在一個十六進制編輯器中逐字節地查看它,你會看到「01 00 00 00 02 00 00 00」。但是,如果您將視圖更改爲雙字模式,您會看到'00000001 00000002'。 – Michael 2013-05-14 06:34:20
我對第10點的建議是用'-S'選項編譯一個小C例子並檢查生成的彙編代碼。 – Michael 2013-05-14 06:39:18