首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C指針原理匯編視角(95):陣列初始化、列印迴圈與棧幀交互實戰

     編輯:關於C

前言

從匯編角度觀察 C 指針與陣列操作,能建立「代碼→指令→硬體」的立體認知。本文分析一段 x86 AT&T 語法匯編:在 .data 區定義 10 整數陣列,迴圈初始化 0~9,再迴圈呼叫 printf 列印,展示指標算術、棧幀保存/恢復、呼叫約定細節。

一、匯編代碼全文註釋


.section .rodata               // 唯讀資料段
output:
    .asciz "the number is %d\n"  // 格式字串(以 \0 結尾)

.section .data                 // 已初始化可讀寫資料段
value:
    .int 0,0,0,0,0,0,0,0,0,0   // 10 個 int,佔 40 位元組

.section .text                 // 代碼段
.globl main
main:
    movl $0, %ecx              // ecx = 0 (迴圈計數器)

loopset:                       // 初始化迴圈
    // 基址寻址:value(基址, %ecx索引, 4比例因子) → value + ecx*4
    movl %ecx, value(, %ecx, 4)  // value[ecx] = ecx
    inc %ecx                   // ecx++
    cmpl $10, %ecx             // ecx == 10 ?
    jne loopset                // 不等則跳回

    movl $0, %ecx              // 重置 ecx = 0

loopprint:                     // 列印迴圈
    movl value(, %ecx, 4), %eax  // eax = value[ecx] (參數1)
    pushl %ecx                 // 保存 ecx (printf 可能破壞)
    pushl %eax                 // 參數2:要列印的整數
    pushl $output              // 參數1:格式字串地址
    call printf                // 呼叫 C 庫函數
    addl $8, %esp              // 清理參數:pop 2 個 push (eax, output),各 4 位元組
    popl %ecx                  // 恢復 ecx
    inc %ecx
    cmpl $10, %ecx
    jne loopprint              // 迴圈 10 次
    // 隱式返回 0 (eax=0)

二、關鍵技術點深度解析

1. 基址+索引+比例因子寻址模式

value(, %ecx, 4) 對應 Intel 語法 [value + ecx*4]。

  • 基址:value 陣列起始地址。
  • 索引:%ecx (0~9)。
  • 比例:4 (int 大小)。
  • 此模式**完美映射 C 陣列下標** value[ecx],無需手動乘法指令。

2. 棲幀保存:pushl %ecx / popl %ecx

  • printf 遵循 **cdecl 呼叫約定**:%eax, %ecx, %edx 為調用者保存暫存器。
  • 迴圈計數器 %ecx 必須在 call 前保存,返回後恢復,否則迴圈邏輯錯亂。

3. 參數傳遞與棧清理(cdecl)

  • 參數**從右向左**壓棧:push format, push value。
  • call 後由**調用者**清理棧:addl $8, %esp (2參數 × 4字節)。
  • 返回值在 %eax。

4. 棧增長方向與 esp/ebp

  • 棧**向低地址增長**:push → esp -= 4;pop → esp += 4。
  • 本例未建立 ebp 幀指標(葉子函數、優化),直接用 esp 相對寻址。

三、編譯與運行驗證


$ gcc -o test1 test1.s
$ ./test1
the number is 0
the number is 1
...
the number is 9

四、對應 C 代碼重構


#include 
int main() {
    int value[10];
    for (int i = 0; i < 10; i++) value[i] = i;
    for (int i = 0; i < 10; i++) printf("the number is %d\n", value[i]);
    return 0;
}

五、總結

這段匯編展示了 C 陣列下標如何編譯為 **基址+索引×比例** 寻址、迴圈計數器如何跨函數呼叫保存、cdecl 參數右進左出與調用者清棧。理解這些機制,是掌握指針算術、調試崩潰棧幀、編寫高效內聯匯編的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved