2011-05-06 37 views
2

我想我開始明白怎麼回事,但現在我已經花年齡試圖理解爲什麼下面不工作:訪問此字符串常量的此程序集有什麼問題?

org 0x7C00 

mov ax,0x0000 
mov ds,ax 

mov si, HelloWorld 

HelloWorld db 'Hello World',13,10,0 

什麼我期待的是,mov si, HelloWorld指令將將0x7C08的值設置爲si(即0x7c00 + HelloWorld的偏移量),準備好像lodsb之類的值。

當我建立這個(使用NASM),並運行它(使用Bochs的)我找到了該結束的指令,實際上是這樣的:

mov si, 0x8400 

這是爲什麼,而其中的值是0x8400來自?

更新:我發現,在數據段將HelloWorld產生預期的輸出:

section .data 
HelloWorld db 'Hello World',13,10,0 

這是爲什麼?

FYI用於構建該命令是nasm -f bin input.asm -o output.bin

更新2我突然意識到0x84000x7c00 + 0x0800,其中8是從輸出開始偏移的HelloWorld - 我注意到這一點,當我發現當使用org 0時,使用的地址是0x0800

我仍然不明白髮生了什麼 - 雖然發現這只是讓我更加困惑!

按照要求,使用ndisasm拆解:

00000000 B80000   mov ax,0x0 
00000003 8ED8    mov ds,ax 
00000005 BE0084   mov si,0x8400 
00000008 48    dec ax 
00000009 656C    gs insb 
0000000B 6C    insb 
0000000C 6F    outsw 
0000000D 20576F   and [bx+0x6f],dl 
00000010 726C    jc 0x7e 
00000012 640D0A00   fs or ax,0xa 
+1

你如何建立和運行它?以下是我所看到的: 'mov si,07C08' – 2011-05-06 16:12:03

+1

您是否在nasm命令行上使用了任何特殊標誌?當我通過nasm運行上面的代碼時,我得到了你期望的。 – Aaron 2011-05-06 16:14:46

+0

是的,給我們完整的'nasm'命令行來重現這一點。 – NPE 2011-05-06 16:19:03

回答

1

升級您的nasm副本。

使用NASM 2.09rc1我得到以下(意外)拆卸:

00000000 B80000   mov ax,0x0 
00000003 8ED8    mov ds,ax 
00000005 BE0084   mov si,0x8400 
00000008 48    dec ax 
00000009 656C    gs insb 
0000000B 6C    insb 
0000000C 6F    outsw 
0000000D 20576F   and [bx+0x6f],dl 
00000010 726C    jc 0x7e 
00000012 640D0A00   fs or ax,0xa 

使用NASM 08年9月2日,我得到以下(預期)拆卸:

00000000 B80000   mov ax,0x0 
00000003 8ED8    mov ds,ax 
00000005 BE087C   mov si,0x7c08 
00000008 48    dec ax 
00000009 656C    gs insb 
0000000B 6C    insb 
0000000C 6F    outsw 
0000000D 20576F   and [bx+0x6f],dl 
00000010 726C    jc 0x7e 
00000012 640D0A00   fs or ax,0xa 

我想這是一個發佈候選人的原因... :)

+0

再次感謝您的幫助 - 我現在感覺有點聰明(現在我意識到我的程序集一直都是正確的),而且對於管理安裝錯誤的版本來說真的很愚蠢! – Justin 2011-05-07 06:13:24

0

嗯...... 'H' 是0x48。也許你在拉取'Hello World'的第一個字節而不是地址。

+0

什麼會將半字節翻轉爲0x84? – 2011-05-06 16:11:41

+0

我也在想 - 除了那個值將是0x4800,而不是0x8400。另外 - 這是一個16位移動。 – Aaron 2011-05-06 16:13:25

+0

我想知道這一點,所以試圖改變字符串開始與另一個字符,但我得到了相同的價值,所以得出結論,這只是一個巧合。 – Justin 2011-05-06 16:16:52

2

除非您使用bin格式,否則允許nasm將您的數據移動到segment .data這在編譯爲PE格式(如.EXE)時非常有用。

換句話說,你確定0x8400是不是正確的地址,一旦輸出二進制已經佈局和鏈接?我知道您正在嘗試發出segment .text中的數據 - 爲此,我認爲您需要bin指令。

編輯:

既然你使用的是bin格式,並考慮您的附加信息,建立了HelloWorld字符串中segment .data不工作,我懷疑你需要做的是:

lea si, [cs:HelloWorld] 

我可能會忽略語法 - 我已經使用16位x86編碼已經有好幾年了 - 但重要的是,您正在根據關於ds的值的假設得到一個抵消值,您明確要清除這個值,以及彙編器可能會假設其值爲segment .code或類似的。 (感謝阿龍糾正我的MOV的執法機關。)

+0

所以我使用'-f bin',同時'0x7C08'是我調試時字符串的實際地址。 – Justin 2011-05-06 16:25:49

+0

我認爲語法是'mov si,[cs:HelloWorld]',但是NASM只產生'mov si,[ds:0x8400]',我仍然不明白。 – Justin 2011-05-07 05:36:29

+0

@Kragen - 我相信最後一條語句將地址'[cs:HelloWorld]'中的數據移動到si中 - 而不是地址。要移動你需要的地址'lea si,[cs:HelloWorld]''。但我不相信這實際上是你想要的。 – Aaron 2011-05-07 05:48:44

1

MASM幫助:

包含代碼 應該啓動它的代碼段與 線像RESB 100h的第一目標文件。這是爲了 確保代碼開始於偏移相對於 代碼段的開始 100H,使得接頭或 轉換器程序沒有生成.COM文件時 調整 文件內地址的引用。 其他裝配使用ORG指令 爲了這個目的,但是ORG在NASM是 特定格式的指令到bin 輸出格式,因爲它在 MASM兼容彙編確實並不意味着 同樣的事情。

因此,你有代碼段CS和數據段DS,它們不相等,因此標籤指針也不同,取決於節。 在x86下,段對齊通常是4096字節,它適合內存頁的大小。

+0

但它們沒有被0x100關閉,它們被0x800關閉 - 這是一個虛擬機頁面(4096字節),讓我想知道他的@data是否等於他的@text減去0x800--給PE或MZ頭在EXE上。 – 2011-05-06 19:10:49

+0

不,不要在程序啓動之前先啓動手動DS和SC(SS也)段寄存器。正確的CS和DS值寫入程序頭表中。 CS和DS之間的內存空間是在編譯時定義的(通常至少有一個內存頁)。因此,你必須使用節.text,.data和.bss – 2011-05-06 19:28:10

+0

這是一個引導程序,所以沒有程序頭表。 – Justin 2011-05-07 05:00:52