Professional Documents
Culture Documents
第 3 章、組合語言
作者:陳鍾誠
旗標出版社
第 3 章、組合語言
3.1 簡介
3.2 基本範例
3.3 進階範例
3.4 函數與副程式
3.5 實務案例
有系統的移動資料
在半導體電路當中,只有一種東西在流動著,那就是電子
程式有系統的搬動電子
組合語言指令
將資料搬來搬去
最多加上一些計算
計算也是在有系統的搬動資料
指令的執行過程
組合語言指令
移動指令
算術指令
邏輯運算指令
移位指令
載入儲存指令
跳躍指令
比較指令
條件式跳躍指令
移動指令
暫存器
ALU
( 加法器… )
R1=00000002
R2=00000002
Control Unit
IR=12120000
( 控製單元 ) (MOV R1, R2)
暫存器
ALU
( 加法器… )
R1=00000005
R2=00000002
R3=00000003
Control Unit
IR=13123000
( 控製單元 ) (ADD R1, R2, R3)
暫存器
ALU
( 加法器… )
R1=00000001
R2=00000002
R3=00000003
Control Unit
IR=14132000
( 控製單元 ) (SUB R1, R3, R2)
暫存器
ALU
( 加法器… ) R1 ( 二進位 ) = * 0100 0001
R1=00000041
Control Unit
IR=1A123000
( 控製單元 ) (XOR R1, R2, R3)
移位指令
ALU
( 加法器… )
暫存器
R1=00000410
R2=00000041
Control Unit
( 控製單元 ) IR=1E120004
LD R1, [0x28] 00 10 00 28
ALU 暫存器
( 加法器… ) R1=0F 0A C0 25 0028 0F 0A C0 25
ST R1, [0x32] 01 10 00 32
ALU 暫存器
( 加法器… ) R1=0F 0A C0 25 0032 0F 0A C0 25
新的 PC 值
PC=0058
IR = 0E 00 00 30 PC = 00 00 00 28
狀態暫存器 N Z C V I T M
Status Word (SW)
31 -28 27 - 8 7 6 5-1 0
ALU 暫存器
( 加法器… ) R1=00 00 00 01
R2=00 00 00 02
IR = 10 12 00 00
Control Unit
( 控製單元 ) SW= 80 00 00 00
新的 PC 值
PC=00C9
IR = 0C 00 00 47 PC = 00 00 00 82
SW =80 00 00 00
數學運算
if 判斷
模擬迴圈
完整範例:從 1 加到 10
範例 3.1 C 語言當中的指定敘述 - 資料流動指
令
void main() {
int x = 3, y;
y = x;
}
範例 3.2 組合語言當中的資料移動指令 - MOV
組合語言 C 語言
MOV R1, R2 R1 = R2
範例 3.3 以組合語言模擬 C 語言當
中的指定敘述 A=B
組合語言 C 語言 ( 對照 C 語言 ( 簡化
LD R1, B 版 )= B
R1 版=
A ) B
ST R1, A A = R1
範例 3.4 以組合語言模擬 C 語言當
中的數學運算式 A = B + C - D
組合語言 C 語言 ( 對照 C 語言 ( 簡化
LD R2, B 版 )= B
R2 版=
A ) B+C–
LD R3, C R3 = C D
LD R4, D R4 = D
ADD R1, R2, R1 = R2 +
R3 R3
SUB R1, R1, R1 = R1 – R4
R4 A = R1
ST R1, A
範例 3.5 以組合語言模擬 C 語言當
中的 if 判斷式
組合語言 C 語言 ( 對照版 ) C 語言
LD R1, A R1 = A;
LD R2, B R2 = B; If
CMP R1, R2 If (R1 > R2) (A>B)
JGT goto LABEL1; C=
LABEL1 C = R2; A;
ST R2, C goto LABEL2 else
JMP LABEL1: C=
LABEL2 C = R1 B;
LABEL1: LABEL2:
ST R1, C
LABEL2:
範例 3.6 以組合語言實作無窮迴
圈
組合語言 C 語言 ( 對照版 )
LOOP: while (1) {
ADD R1, R2, R1 R1 = R1 + R2;
JMP LOOP }
範例 3.7 組合語言的完整程式範例,
加總迴圈,從 1 加到 10 。
組合語言 C 語言 ( 對照版 ) C 語言 ( 簡化版 )
1 START void main() { void main() {
2 LD R1, sum R1 = sum; int sum=0;
3 LD R2, I R2 = i; int i;
4 LD R3, ten R3 = ten; for (i=0;
5 LD R4, one R4 = one; i<=10; i++)
6 FOR: CMP R2, R3 if (R2 > R3)//(i > sum += i;
7 JGT EXIT 10) }
8 ADD R1, R2, R1 goto EXIT;
9 ADD R2, R4, R2 R1 = R2 + R1;
10 JMP FOR R2 = R2 + R4;
11 EXIT: RET goto FOR;
12 i RESW 1 EXIT: return;
13 Sum WORD 0 int i;
14 Ten WORD 10 int sum = 0;
15 One WORD 1 int ten = 10;
16 END int one = 1;
}
3.3 進階範例
字串複製 ( 指標版 )
字串複製 ( 索引版 )
整數陣列的複製
複雜結構的存取
範例 3.9 字串複製 ( 索引版 )
組合語言 C 語言 ( 對照版 ) C 語言 ( 真實版 )
START void main() { void main() {
LD R1, I R1=i; char a[10];
LD R2, aptr R2=*aptr; char b[] = "Hello !";
LD R3, bptr R3=*bptr; char *aptr=a, *bptr=b;
LD R7, one R7=one; while (1) {
while: while: *aptr = *bptr;
LDB R4, [R3] R4 = [R3]; // R4 = *bptr aptr++;
STB R4, [R2] [R2] = R4; //*aptr = R4 bptr++;
ADD R2, R2, R2= R2+1; if (*bptr == '\0')
R7; R3=R3+1; break;
ADD R3, R3, if (R4!= R0) // b[i] != '\0' }
R7; goto endw; return;
CMP R4, R0 goto while; }
JEQ endw endw: return;
JMP while char a[10];
endw: RET char b[] = "Hello !"
A RESB 10 int i=0;
B BYTE "Hello ! int one = 1;
",0 int *aptr = a;
i WORD 0 int *bptr = b;
one WORD 1 }
aptr WORD &a
字串複製 ( 索引版 )
組合語言 C 語言 ( 對照版 ) C 語言 ( 真實版 )
START void main() { void main() {
LD R1, I R1=i; char a[10];
LD R2, aptr R2=*aptr; char b[] = "Hello !";
LD R3, bptr R3=*bptr; int i = 0;
LD R7, one R7=one; while (1) {
while: while: a[i] = b[i];
ADD R5, R3, R1 R5 = R3+R1;// R5=&b[i] if (b[i] == '\0')
LDB R4, [R5] R4 = [R5]; // R4 = b[i] break;
ADD R6, R2, R1 R6 = R2+R1;// R6=&a[i] i++;
STB R4, [R6] [R6] = R4; // a[i] = R4 }
CMP R4, R0 if (R4!= R0) // b[i] != '\0' return;
JEQ endw goto endw; }
ADD R1, R1, R7 R1 = R1 + R7; // i++;
JMP while goto while;
endw: RET endw: return;
A RESB 10 char a[10];
B BYTE "Hello !",0 char b[] = "Hello !"
aptr WORD &a int *aptr=a;
bptr WORD &b int *bptr=b;
i WORD 0 int i=0;
one WORD 1 int one = 1;
END }
範例 3.10 陣列複製 ( 索引版 )
組合語言 組合語言 C 語言
START void main() { int a[100], b[100];
LD R2, aptr R2 = *aptr; int i;
LD R3, bptr R3 = *bptr; for (i=0; i<=100; i++) {
LDI R8, 1 R8 = 1; a[i] = b[i];
LDI R9, 100 R9 = 100; }
ST R0, i i = 0;
LD R1, i R1 = i;
FOR: FOR:
SHL R5, R1, 2 R5 = R1 << 2; //
ADD R6, R5, R2 R5=i*4;
ADD R7, R5, R3 R6 = R5 + R2; //
LD R5, [R6] R6=&a[i]
ST R5, [R7] R7 = R5 + R3; //
ADD R1, R1, R8 R7=&b[i]
CMP R1, R9 R5 = [R6]; // R5 = a[i]
JLE FOR [R7] = R5; // b[i] = R5;
RET R1 = R1+1; // i++;
a RESW 100 If (R1 < R9) // i<=100
b RESW 100 goto FOR;
aptr WORD &a return
bptr WORD &b int a[100];
i RESW 1 int b[100];
END int *aptr=a;
範例 3.11 複雜結構的存取
組合語言 C 語言 ( 對照版 ) C 語言 ( 真實版 )
START void main() { typedef struct {
… … char name[20];
LDI R5, 20 R5 = 20; int age;
LD R1, pptr R1 = *pptr; } person;
ADD R2, R1, R5 R2 = R1 + R5;// p + 20; void main() {
LDI R6, 18 R6 = 18; person p;
ST R6, [R2] [R2] = R6; // [p+20] = …
… 18; p.age = 18;
p RESB 24 … …
pptr WORD &p char p[24]; }
END int *pptr = &p;
}
3.4 函數與副程式
副程式呼叫
呼叫:跳躍指令 JSUB
返回:返回指令 RET
參數的傳遞方法
透過暫存器傳遞參數給副程式
透過堆疊進行多層次的副程式呼叫
範例 3.12 單層副程式的呼叫
- 以暫存器傳遞參數
語法
MASM 與 NASM 以 Intel 語法為基礎
但各自進行了擴充。
中斷資料區 (0x400-0x470)
中斷處理函數
int $0x10 :可呼叫第 10 號中斷,在螢幕上輸出字
串
表格 3.1 個人電腦的 BIOS 資料
區
位移 說明 位移 說明
0000-0007 COM1-COM4 埠位 004A- 螢幕的欄數
0008-000F LPT1-LPT4
址 埠位址 004B
004C- 視訊緩衝區的長度
0010-0011 已安裝的硬體清單 004D
004E- 視訊緩衝區的起點
0012 初始化旗標 0050-
004F 游標位址 (8 個視訊頁 )
0013-0014 記憶體的大小 (KB) 005F
0060 游標結束列
0015-0016 I/O 通道的記憶體 0061 游標起始列
0017-0018 鍵盤的狀態旗標 0062 目前顯示的視訊頁編號
0019 替代鍵的儲存區 0063- 作用中的視訊基底位址
001A- 鍵盤緩衝區指標 ( 頭 0064
0065 CRT 模式暫存器
001C-
001B )
鍵盤緩衝區指標 (尾 0066 彩色圖形介面卡的暫存器
001D
001E- )
鍵盤緩衝區 0067- 卡帶磁帶資料區
003D
003E-0048 磁碟資料區 006B
006C- 計時器資料區
0049 目前的視訊模式 0070
表格 3.2 個人電腦 PC 的中斷表
(1)
編號 說明 編號 說明
0 除法錯誤 19 啟動程式載入器
1 單步追蹤 1A 本日時間 ( 單位為 18.2 次 / 秒 )
2 不可遮罩中斷 1B 鍵盤中斷
3 中斷點 1C 使用者計時器中斷
4 溢位 1D 視訊參數
5 列印螢幕 1E 磁碟參數
6 無效的運算碼 1F 繪圖表格
7 無法使用處理器擴充 20 終止程式
8 IRQ0 計時器中斷 (18.2 次 21 MS-DOS 服務
9 / 秒 ) 鍵盤中斷
IRQ1 22 MS-DOS 終止服務
A IRQ2 可程式化中斷控制器 23 MS-DOS 中斷位址
B IRQ3 序列通訊 (COM2) 24 MS-DOS 嚴重錯誤位址
表格 3.2 個人電腦 PC 的中斷表
(2)
C IRQ4 序列通訊 (COM1) 25 絕對磁碟的讀取 ( 已棄用 )
D IRQ5 固定磁碟 26 絕對磁碟的寫入 ( 已棄用 )
E IRQ6 磁碟中斷 27 終止並且常駐 ( 已棄用 )
F IRQ7 平行印表機 28-FF 保留
10 視訊服務 ( 螢幕 ) 33 滑鼠控制
11 設備檢查 34-3E 浮點樹模擬
12 記憶體大小 3F 覆蓋 (Overlay) 管理程式
13 軟碟服務 40-41 固定磁碟的服務
14 非同步序列埠服務 42-5F 保留:特殊用途
15 卡帶控制器 60- 可供應用程式使用
16 鍵盤服務 6C-7F
6B 保留:特殊用途
17 印表機服務 80-F0 保留:由 ROM-BASIC 使用
18 執行 ROM 中的 BASIC F1-FF 可供應用程式使用
表格 3.3 BIOS 第 10 號中斷 – 銀幕
控制的詳細功能 (1)
AH 功能 參數
0 設置顯示方式 AL= 顯示模式( 0 ~ 13H )
1 設置游標類型 CH= 游標開始行
CL= 游標結束行
2 設置游標位置 BH= 頁號; DH/DL = 行號 / 列號
3 讀游標位置 BH= 頁號
5 設置當前顯示頁 AL= 頁號
6 螢幕初始化或上卷 AL= 上卷行數; AL=0 全螢幕為空白
BH= 捲入行屬性
CH/CL= 左上角行號 / 列號
DH/DL= 右上角行號 / 列號
7 螢幕初始化或下卷 AL= 下卷行數; AL=0 全螢幕為空白
BH= 捲入行屬性
CH/CL= 左上角行號 / 列號
DH/DL= 右上角行號 / 列號
表格 3.3 BIOS 第 10 號中斷 – 銀幕
控制的詳細功能 (2)
…
mov $msg, %ax
mov %ax,%bp #ES:BP = 串地址
mov $6,%cx #CX = 串長度
mov $0x1301,%ax #AH = 13, AL = 01h
mov $0x00C,%bx # 頁號為 0(BH = 0) 黑底紅
字 (BL = 0Ch)
mov $0,%dl
int $0x10 #10h 號中斷
ret
msg:.ascii "Hello!"
…
MS. DOS 系統中的組合語言
MS. DOS 的組合語言
較為簡單很多組合語言課程
學習者可以任意操控系統
不會受到保護模式的限制。
MASM32
下載 MASM32 組譯器並安裝
C:\MASM32 資料夾中附有許多進階的組合語言範例
包含許多組合語言版的 MS. Windows 視窗程式
MASM32 雖然全名為 Microsoft Assembler ,但卻不是現在
Microsft Visual Studio 中所使用的組譯器
因為現在 Visual Studio 中所使用的是 ML 這個組譯連結器
您可以在 http://www.masm32.com/ 這個網站中下載 MASM32
這個組譯器。
範例 3.18 以 MASM32 撰寫組合語
言以顯示對話視窗的範例 ( 頁 1)
.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include \masm32\include\dialogs.inc
include simple.inc
dlgproc PROTO :DWORD,:DWORD,:DWORD,:DWORD
.code
start:
mov hInstance, FUNC(GetModuleHandle,NULL)
call main
invoke ExitProcess,eax
main proc
Dialog "Simple Dialog","MS Sans Serif",10, \ ; caption,font,pointsize
WS_OVERLAPPED or WS_SYSMENU or DS_CENTER, \ ; style
2, \ ; control count
50,50,150,80, \ ; x y co-ordinates
1024 ; memory buffer size
DlgButton "&OK",WS_TABSTOP,48,40,50,15,IDCANCEL
DlgStatic "Simple Dialog Written In MASM32",SS_CENTER,2,20,140,9,100
CallModalDialog hInstance,0,dlgproc,NULL
ret
main endp
範例 3.18 以 MASM32 撰寫組合語
言以顯示對話視窗的範例 ( 頁 2)
dlgproc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
.if uMsg == WM_INITDIALOG
invoke
SendMessage,hWin,WM_SETICON,1,FUNC(LoadIcon,NULL,IDI_ASTERISK)
.elseif uMsg == WM_COMMAND
.if wParam == IDCANCEL
jmp quit_dialog
.endif
.elseif uMsg == WM_CLOSE
quit_dialog:
invoke EndDialog,hWin,0
.endif
xor eax, eax
ret
dlgproc endp
end start
範例 3.18 的執行結果
3.5.2 ARM 的組合語言
ARM 的定址模式
圖 3.12 ARM 處理器的定址的範
例
範例 語意 說明
LDR Rd, [Rn, ± Rd[Rn± 前置索引
Rd, [Rn, ±
offset]
LDR offset]
Rd[Rn± 寫回運算 (!)
offset]! offset]
LDR [Rn], ±offset RnRn±offset
Rd[Rn] 後置索引
RnRn±offset
LDR Rd, [Rn, ±Rm] Rd[Rn±Rm] 前置索引 ( 使用 Rm)
LDR Rd, [Rn, ±Rm]! Rd[Rn±Rm] 前置索引 + 寫回運算
RnRn±Rm
LDR Rd, [Rn], ±Rm Rd[Rn] 後置索引 ( 使用 Rm)
RnRn±Rm
LDR Rd, [Rn, ±Rm Rd[Rn± 移位後載入
Rd, [Rn, ±Rm
LSL Cx]
LDR Rm<<Cx]
Rd[Rn± 移位後載入 ( 移位量由暫
LSL Rx] Rm<<Rx] 存器 Rx 指定 )
LDR Rd, [±offset] Rd[PC± 相對於程式計數器的定址
offset]
常數的表示:旋轉立即數
旋轉立即數
<rotated_immed>=<immed8> ROR (2*<immed4>)
哪些數字『屬於』旋轉立即數?
0xFF 、 0x104 、 0xBC00000
哪些數字『不屬於』旋轉立即數?
0x0101 和 0x102
常數的設定
對於旋轉立即數 (ex: 972)
可以直接設定
Ex : mov R3, #972
組合語言指令通常用來有系統的移動資料
3.2 基本範例
範例:從 1 加到 10
3.3 進階範例
字串複製、陣列複製、複雜結構存取
本章摘要 (2)
3.4 函數與副程式
透過 JSUB 呼叫與 RET 返回
透過暫存器傳遞參數、或透過堆疊傳遞參數
3.5 實務案例
3.5.1 IA32 的組合語言
MASM (Intel 語法 ) 與 GNU as (AT&T 語法 )