2013-05-04 21:02:07Morris
[組合語言][作業] link 高階語言&中斷點初探
作業內容描述:
助教Demo2.png
助教Demo3.png
助教Demo1.png
作業心得:
操作 Visual Studio 的環境,以及使用裡頭的 ASM 建模,尤其是在建立中斷點的時候,發現不能直接在 .asm 中設立中斷點,因此需要跑到新增中斷點->函式中斷,而那邊所打的行數並非程式碼的總行數,而是以相對函式標頭的距離行數。
此外在記憶體監控的部分仍有疑惑,這次很明顯地可以直接使用變數名稱打入,又或者是查看暫存器得到記憶體位址,但如果是要求的是區間變數,但是同名的話,目前還不知道怎麼操作。
ASM 的指令還不熟悉,以為 USES 的暫存器之間要打上逗號(,)。
自己用C/C++ 的語法打 convertPattern
void convertPattern(unsigned int BitArr[][16], char StarArr[][16][16]) {
unsigned int *p = &BitArr[0][0];
char *q = &StarArr[0][0][0];
for(int i = 0; i < 48; i++) {
for(int j = 15; j >= 0; j--)
*q++ = (*p)&(1<<j) ? '*' : ' ';
p++;
}
}
如果使用指標的方式進行,編譯器產生的 ASM代碼會比較接近我們所想的。
首先先討論 debug 與 release 的差別,那麼可以發現在 for 迴圈的指令解析上 release 會將其優化(如果可以優化),改變成 do_while 的形式,計算判斷次數比 debug 的次數來得少,速度也會比較快。
上網搜索了有關於 debug 與 release 的差別,根據描述說明了 debug 會保留 ebp,而 release 不會,是以一個全區變數去指向堆疊。雖然看起來 release 是比 debug 優化了許多,如常數折疊、判斷壓縮,但不一定程式碼就比較短。
比較一下,C/C++ 與 ASM 的 function code,由於基本上 C/C++ 沒有加上 “register” 的修飾字都是 stack dynamic,因此在存取速度比 ASM 還來得慢。因此自行撰寫 ASM 的速度會比較快。
但是在組譯碼的觀察中,沒有看到如 eax, ebx … 等暫存器,還不是很了解其內容。
作業筆記:
設了中斷點後,可以持續按著 "繼續(F5)" 觀察記憶體狀況。
這個是最後的結果
記得按下 "偵錯(即一個開始鍵)",才能打開視窗中的記憶體觀察,否則只會有少數幾個選項。
打上位址有兩種方式,打變數名稱(按下 Enter 會轉換成記憶體位址),
又或者去看暫存器,將其打入即可,"資料行" 是控制一行有多少個 bytes 顯示。
接下來講中斷點的部分,會發現 ASM 中沒辦法插入中斷點。
拉開選單,找到"在函式中斷"
打上函數名稱,同時打上行數,記住這裡的行數是相對於函式的標頭開始計算,
並不是程式碼的行數,如果打超過,會自動跑到最後一行就是了!
Cpp 的部分:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern "C" {
void convertPattern(unsigned int BitArr[3][16], char StarArr[3][16][16]);
}
unsigned int BitArr[3][16] = {
{0x0000,0x107e,0x1042,0x107e,0xfe42,0x307e,0x3800,0x59ff,
0x94c0,0x11fe,0x124a,0x1492,0x1122,0x10d2,0x100e,0x0000},
{0x0000,0x8800,0x5000,0x53de,0xf842,0x235a,0xf8c6,0x2042,
0x20c6,0xfb5a,0x2042,0x2042,0x2252,0x21ce,0x4042,0x0000},
{0x0000,0x1ff8,0x0100,0x7ffe,0x5112,0x4d62,0x4d62,0x5912,
0x4002,0x1ff8,0x0000,0x7ffe,0x0200,0x0410,0x0ff8,0x0004}
};
char StarArr[3][16][16];
/*void convertPattern(unsigned int BitArr[][16], char StarArr[][16][16]) {
unsigned int *p = &BitArr[0][0];
char *q = &StarArr[0][0][0];
for(int i = 0; i < 48; i++) {
for(int j = 15; j >= 0; j--)
*q++ = (*p)&(1<<j) ? '*' : ' ';
p++;
}
}*/
int main() {
convertPattern(BitArr, StarArr);
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 16; j++) {
for(int k = 0; k < 16; k++) {
putchar(StarArr[i][j][k]);
}
puts("");
}
puts("");
}
system("PAUSE");
return 0;
}
.asm 的部分
TITLE convertPattern Procedure (convert.asm)
.586
.model flat,C
convertPattern PROTO C,
BitArr:PTR DWORD, StarArr:PTR DWORD
.code
;---------------------------------------------
convertPattern PROC USES edi esi eax ecx,
BitArr:PTR DWORD, StarArr:PTR DWORD
;
;
;
;
;---------------------------------------------
mov esi, BitArr
mov edi, StarArr
mov ecx, 3 * 16
L1: push ecx
mov ax, WORD PTR[esi]
mov ecx, 16
L2: shl ax, 1
mov BYTE PTR [edi], ' '
jnc L3
mov BYTE PTR [edi], '*'
L3: add edi, 1
loop L2
add esi, 4
pop ecx
loop L1
ret
convertPattern ENDP
END
- A main program in C++
- Declare:
- unsigned int BitArr[3,16];
char StarArr[3,16,16]; - BitArr are initialized with the last three characters of your Chinese name in bit string format.
- A masm procedure: Convert 0 to blank and 1 to * for each bit in BitArr of a Chinese character to the corresponding locations in StarArr.
- The C++ main program calls the masm procedure to convert the BitArr to StarArr.
- 編寫一個C++的主程式,並且在內部宣告:
unsigned int BitArr[3][16];
char StarArr[3][16][16];
BitArr 的初始值內容必須是你中文名字的Bit Pattern. - 另外再寫一個組語procedure,功能是: 將BitArr的各個Bit轉換為Char,bit 0 轉變為空白,bit 1轉為星號,結果逐一放入StarArr.
- C++主程式必須呼叫組語寫的procedure來轉換BitArr 成StarArr.
助教Demo2.png
助教Demo3.png
助教Demo1.png
作業心得:
操作 Visual Studio 的環境,以及使用裡頭的 ASM 建模,尤其是在建立中斷點的時候,發現不能直接在 .asm 中設立中斷點,因此需要跑到新增中斷點->函式中斷,而那邊所打的行數並非程式碼的總行數,而是以相對函式標頭的距離行數。
此外在記憶體監控的部分仍有疑惑,這次很明顯地可以直接使用變數名稱打入,又或者是查看暫存器得到記憶體位址,但如果是要求的是區間變數,但是同名的話,目前還不知道怎麼操作。
ASM 的指令還不熟悉,以為 USES 的暫存器之間要打上逗號(,)。
自己用C/C++ 的語法打 convertPattern
void convertPattern(unsigned int BitArr[][16], char StarArr[][16][16]) {
unsigned int *p = &BitArr[0][0];
char *q = &StarArr[0][0][0];
for(int i = 0; i < 48; i++) {
for(int j = 15; j >= 0; j--)
*q++ = (*p)&(1<<j) ? '*' : ' ';
p++;
}
}
如果使用指標的方式進行,編譯器產生的 ASM代碼會比較接近我們所想的。
首先先討論 debug 與 release 的差別,那麼可以發現在 for 迴圈的指令解析上 release 會將其優化(如果可以優化),改變成 do_while 的形式,計算判斷次數比 debug 的次數來得少,速度也會比較快。
上網搜索了有關於 debug 與 release 的差別,根據描述說明了 debug 會保留 ebp,而 release 不會,是以一個全區變數去指向堆疊。雖然看起來 release 是比 debug 優化了許多,如常數折疊、判斷壓縮,但不一定程式碼就比較短。
比較一下,C/C++ 與 ASM 的 function code,由於基本上 C/C++ 沒有加上 “register” 的修飾字都是 stack dynamic,因此在存取速度比 ASM 還來得慢。因此自行撰寫 ASM 的速度會比較快。
但是在組譯碼的觀察中,沒有看到如 eax, ebx … 等暫存器,還不是很了解其內容。
作業筆記:
設了中斷點後,可以持續按著 "繼續(F5)" 觀察記憶體狀況。
這個是最後的結果
記得按下 "偵錯(即一個開始鍵)",才能打開視窗中的記憶體觀察,否則只會有少數幾個選項。
打上位址有兩種方式,打變數名稱(按下 Enter 會轉換成記憶體位址),
又或者去看暫存器,將其打入即可,"資料行" 是控制一行有多少個 bytes 顯示。
接下來講中斷點的部分,會發現 ASM 中沒辦法插入中斷點。
拉開選單,找到"在函式中斷"
打上函數名稱,同時打上行數,記住這裡的行數是相對於函式的標頭開始計算,
並不是程式碼的行數,如果打超過,會自動跑到最後一行就是了!
Cpp 的部分:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern "C" {
void convertPattern(unsigned int BitArr[3][16], char StarArr[3][16][16]);
}
unsigned int BitArr[3][16] = {
{0x0000,0x107e,0x1042,0x107e,0xfe42,0x307e,0x3800,0x59ff,
0x94c0,0x11fe,0x124a,0x1492,0x1122,0x10d2,0x100e,0x0000},
{0x0000,0x8800,0x5000,0x53de,0xf842,0x235a,0xf8c6,0x2042,
0x20c6,0xfb5a,0x2042,0x2042,0x2252,0x21ce,0x4042,0x0000},
{0x0000,0x1ff8,0x0100,0x7ffe,0x5112,0x4d62,0x4d62,0x5912,
0x4002,0x1ff8,0x0000,0x7ffe,0x0200,0x0410,0x0ff8,0x0004}
};
char StarArr[3][16][16];
/*void convertPattern(unsigned int BitArr[][16], char StarArr[][16][16]) {
unsigned int *p = &BitArr[0][0];
char *q = &StarArr[0][0][0];
for(int i = 0; i < 48; i++) {
for(int j = 15; j >= 0; j--)
*q++ = (*p)&(1<<j) ? '*' : ' ';
p++;
}
}*/
int main() {
convertPattern(BitArr, StarArr);
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 16; j++) {
for(int k = 0; k < 16; k++) {
putchar(StarArr[i][j][k]);
}
puts("");
}
puts("");
}
system("PAUSE");
return 0;
}
.asm 的部分
TITLE convertPattern Procedure (convert.asm)
.586
.model flat,C
convertPattern PROTO C,
BitArr:PTR DWORD, StarArr:PTR DWORD
.code
;---------------------------------------------
convertPattern PROC USES edi esi eax ecx,
BitArr:PTR DWORD, StarArr:PTR DWORD
;
;
;
;
;---------------------------------------------
mov esi, BitArr
mov edi, StarArr
mov ecx, 3 * 16
L1: push ecx
mov ax, WORD PTR[esi]
mov ecx, 16
L2: shl ax, 1
mov BYTE PTR [edi], ' '
jnc L3
mov BYTE PTR [edi], '*'
L3: add edi, 1
loop L2
add esi, 4
pop ecx
loop L1
ret
convertPattern ENDP
END
Thank...