在代碼段中用“;”表示注釋
匯編代碼如下:
dp@dp:~ % cat test1.s
.section .rodata
output:
.asciz "the number is %d\n"
.section .data
value:
.int 0,0,0,0,0,0,0,0,0,0
.section .text
.globl main
main:
movl $0,%ecx
loopset:
;基地址(存在寄存器中的偏移地址,存在寄存器中的數據元素索引,存在寄存器中的數據元素大小)
movl %ecx,value(,%ecx,4)
inc %ecx
cmpl $10,%ecx
jne loopset
movl $0,%ecx
loopprint:
movl value(,%ecx,4),%eax
pushl %ecx
pushl %eax
pushl $output
call printf
add $8,%esp
popl %ecx
inc %ecx
cmpl $10,%ecx
jne loopprint
編譯並運行
dp@dp:~ % gcc -o test1 test1.s
dp@dp:~ % ./test1
the number is 0
the number is 1
the number is 2
the number is 3
the number is 4
the number is 5
the number is 6
the number is 7
the number is 8
the number is 9
上述代碼 ,先在.data可讀寫區域放置10個初始值為0的int值,然後在程序中通過loopset標記和jne語句完成一個循環,將它們的值依次賦值為0到9,最後通過loopprint標記和jne語句完成循環,調用c庫的print語句將這些數輸出。
inc表示自增1,而dec表示自減1 。
棧是由高地址向低地址增長的,當棧增加內容,將導致棧頂指針減少,否則,導致棧頂指針增加
在print語句執行返回後,清空執行print在堆棧中的生成垃圾,add $8,%esp,拋棄為調用printf函數准備的參數 ,棧頂有ESP寄存器來定位,壓棧的操作使得棧頂的地址減小,彈出的操作使得棧頂的地址增大,因此這裡相當於直接彈出壓入的2個%eax(指向需要輸出的數據)和$output參數,前面有調用:
pushl %eax
pushl $output
在上面這2個壓棧之前,還調用了
pushl %ecx
其作用在於,保存%ecx的值,因為c庫的printf函數會破壞%ecx寄存器的值,一般使用堆棧來保存可能被破壞的值,執行完printf完畢後,再還原:popl %ecx