[英]Understanding assembly from a gcc output
我正在做一個關於計算機基礎知識的高中課程,我正在嘗試理解匯編代碼並在C中創建一個hello world並用匯編代碼編譯它。 據我所知,“mov r0,r3”將數據從寄存器3移動到寄存器0.但是,我如何計算出r3的值是什么?
下面是我用來理解的匯編代碼:
.arch armv6
.eabi_attribute 27, 3
.eabi_attribute 28, 1
.fpu vfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 34, 1
.eabi_attribute 18, 4
.file "hello.c"
.section .rodata
.align 2
.LC0:
.ascii "Hello World\000"
.text
.align 2
.global main
.type main, %function
main:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 1, uses_anonymous_args = 0
stmfd sp!, {fp, lr}
add fp, sp, #4
ldr r0, .L2
bl printf
mov r0, r3
ldmfd sp!, {fp, pc}
.L3:
.align 2
.L2:
.word .LC0
.size main, .-main
.ident "GCC: (Raspbian 4.9.2-10) 4.9.2"
.section .note.GNU-stack,"",%progbits
以下是我的C代碼:
// Hello World program in C
#include<stdio.h>
main()
{
printf("Hello World");
}
使用GNU調試器,“gdb”!
gdb --args ./store01
啟動GNU調試器。
它應該像控制台一樣。
您可以通過鍵入quit
。
但是當然你想逐步運行程序並檢查寄存器上下文。 所以輸入start
,跳轉到main()並跳過初始化的東西。
然后鍵入disassemble
或disas
以顯示您正在運行的匯編程序。
現在每個鍵入stepi
按照指令運行程序指令。
現在有趣的部分:輸入info registers r3
並觀察輸出!
另一個奇妙的事情:你可以改變運行時的值:嘗試p $r0 = 2
。
那不是全部。
這是官方文檔: https : //www.gnu.org/software/gdb/documentation/
一個好的,小的和有用的教程: http : //thinkingeek.com/2013/01/12/arm-assembler-raspberry-pi-chapter-4
好吧,讓我們分解吧。
stmfd sp!, {fp, lr}
STMFD表示“存儲多個完全降序”。 本質上,它使用寄存器sp
作為下行堆棧指針,並按順序將寄存器fp
和lr
放在堆棧上。 fp
是幀指針, lr
是鏈接寄存器(保存返回地址,后面很重要)。
add fp, sp, #4
將幀指針寄存器設置為等於sp + 4(指向剛存儲fp
)。 這是沒有優化的編譯工件。
ldr r0, .L2
這是將存儲在地址.L2
(在本例中為.LC0
的地址,字符串(well,char數組) "Hello World!\\000"
)中存儲的32位值加載到寄存器r0
。
bl printf
通過在以null結尾的字符串"Hello World"
上調用printf
函數來組裝。 回想一下,指向這個數組的指針只是加載到r0
。 通常,GCC分別使用寄存器r0-r3作為函數的第一,第二,第三和第四個參數。 根據需要,其他參數存儲在堆棧中。
mov r0, r3
這是代碼中的錯誤的指示器,這個版本的GCC沒有捕獲。 基本上,您的函數返回一個類型(假設您從未指定為int
),但您從未指定返回值。 因此,返回值是r3
發生的任何事情,這是未定義的。
ldmfd sp!, {fp, pc}
這與函數開頭編譯的stmfd
指令相反。 但是不是加載到fp, lr
,而是加載到fp, pc
。 這導致lr
的原始值直接移動到程序計數器pc
。 pc
是一個特殊的寄存器,它指向下一條執行的指令。 每次將pc
設置為某個值時,CPU立即開始執行該值指向的代碼。 此屬性用於return
調用例程,因為ARM指令集沒有顯式的ret
操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.