随笔-80  评论-24  文章-0  trackbacks-0
其实一直就对汇编语言没有搞透彻,昨天开始重新拾起操作系统来,重又回到了这个最原始的问题,为什么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 阅读(9505) 评论(0)  编辑 收藏 引用 所属分类: 操作系统