其實一直就對匯編語言沒有搞透徹,昨天開始重新拾起操作系統來,重又回到了這個最原始的問題,為什么db、dw、equ等叫偽指令呢?偽指令到底是什么呢?
今天在bochs重新試驗了一把,終于搞明白了:
首先稱db、dw、equ等為偽指令是因為它們是供匯編器使用的,匯編器如果看到mov等指令,直接將其翻譯成mov對應的機器代碼,這個機器代碼是供計算機識別mov的;但是當匯編器看到db指令后,它不是將其翻譯成機器代碼,因為計算機不識別db指令對應的機器碼,db沒有對應的機器碼,db指令是告訴匯編器我需要在當前內存位置寫入一個字節。這樣在用nasm編譯完這個.asm文件生成純二進制.bin文件后,在文件對應的字節處就已經有這個一字節的數據了。.bin文件加載進內存之后在內存中的映像和文件中相同,只是放到了不同的內存地址起始處。
我們舉例說明更加清楚,假如有如下一段代碼:
文件名:boot.asm
1 org 0x7c00
2 jmp begin
3
4 data1 db 10
5 data2 db 11
6 data3 db 12
7 data4 db 13
8
9 begin:
10 mov ax, cs
11 mov ds, ax
12 mov es, ax
13 mov ss, ax
14 jmp $
15
16 times 510 - ($ - $$) db 0
17 dw 0xaa55
這段代碼是一段boot代碼,當然它什么也不做,僅僅是為了解開我們的迷惑。
下面我們就匯編它,然后用dd寫入虛擬軟盤a.img的第一扇區,然后用bochs加載該軟盤:
1 nasm boot.asm -o boot.bin
2 dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc
我們把斷點設置在0x7c00處,因為這是我們的代碼入口處。然后反匯編內存地址0x7c00~0x7cff之間的內容:
<bochs:1> b 0x7c00
<bochs:2> c
(0) Breakpoint 1, 0x00007c00 in ?? ()
Next at t=12943104
(0) [0x0000000000007c00] 0000:7c00 (unk. ctxt): jmp .+4 (0x00007c06) ; eb04
<bochs:3> u 0x7c00 0x7cff
00007c00: ( ): jmp .+4 ; eb04
00007c02: ( ): or cl, byte ptr ss:[bp+di] ; 0a0b
00007c04: ( ): or al, 0x0d ; 0c0d
00007c06: ( ): mov ax, cs ; 8cc8
00007c08: ( ): mov ds, ax ; 8ed8
00007c0a: ( ): mov es, ax ; 8ec0
00007c0c: ( ): mov ss, ax ; 8ed0
00007c0e: ( ): jmp .-2 ; ebfe
00007c10: ( ): add byte ptr ds:[bx+si], al ; 0000
00007c12: ( ): add byte ptr ds:[bx+si], al ; 0000
00007c14: ( ): add byte ptr ds:[bx+si], al ; 0000
00007c16: ( ): add byte ptr ds:[bx+si], al ; 0000
......
反匯編這段內存之后我們發現0x0000fc02~0x00007c05這四字節恰好是我們用db命令寫入的四個字節(見紅色區域)。
如果我們將四條db代碼放到jmp $下面的話我們會發現反匯編后0a0b 0c0d出現的位置也相應的出現在0x00007c0c~0x00007c0f處。到此已經很顯然,同樣,如果我們在代碼里使用了equ等偽指令,反匯編二進制代碼是不會看到equ的任何痕跡的,因為equ只有匯編器才識別,它類似于c語言中的宏定義?也不完全是,因為匯編中有自己的宏定義;變量賦值?也不是,因為c語言中變量定義需要占用內存空間。
posted on 2011-11-05 00:58
myjfm 閱讀(9744)
評論(0) 編輯 收藏 引用 所屬分類:
操作系統