在学习贺利坚老师的汇编语言课程时,其中有一集是“编制中断处理程序”。
(请关注白色画圈的地方)
然后呢我对这个程序进行了一些小小的改进,因为把这个overflow!打出来还得人工的去查到底有多少个字母,不如搞得自动化一些,在后面加一个0作为字符串结束符(贺老师的前边课程有教过如何实现),顺道我觉得这个 MOV SI 202H 也是靠人工实现的(这个202H是怎么来的,中断的入口地址是0000:0200,do0后面的语句占了2个字节,所以db面的数据起始地址就是0202H了),咱能不能也给他自动化一下,我一想,不就是个偏移地址嘛,有一个方法啊,用0ffset不就完啦。
说干就干,马上开始。
AsaHi:
jmp short K
a:db "OVERFLOWER!!!",0
K:
mov ax,0b800h
mov es,ax
mov di,1950d
mov ax,cs
mov ds,ax
mov si,offset a
BAYUE:
mov cl,byte ptr ds:[si]
mov ch,0
jcxz SUCC
mov byte ptr es:[di],cl
inc di
mov byte ptr es:[di],10011100b
inc di
inc si
jmp short BAYUE
SUCC:nop
mov ax,4c00h
int 21h
CHINA:
(我的这个代码标号可能和上面有些不同,但是基本原理是一致的)
然后。。。。。就出问题了,啊啊啊啊啊啊
出了什么问题呢,就是当我执行0号中断时(除数为零)后,在屏幕上并不能显示字符串,而是一些奇怪扭曲的符号,这是为什么呢,明明天衣无缝啊。。。。
本人才刚大一(虽然马上大二的说),对于bug的处理与软件调试技术也不是很在行,所以经过一番往死里折腾(其实后来这个是很简单,你先执行代码转移程序,然后再用-u去检查一下程序代码的编译情况就完事了,非常简单。。)
我终于知道是哪里出了问题了——
在上段代码中
jmp short K
a:db "OVERFLOWER!!!",0
K:
mov ax,0b800h
mov es,ax
mov di,1950d
mov ax,cs
mov ds,ax
mov si,offset a
mov si,offset a 会被编译为 mov si ,0030
?????????????
为什么,为什么会变成这样?按理说应该是mov si,0202 的说,
在书中,在各种博客中一顿寻找,大家说的都是offset是会返回标号的偏移地址,没毛病啊,我要的就是db 数据的偏移地址啊。
是8086这个芯片的漏洞吗?
是汇编语言自己就有问题吗?
是我的电脑中病毒了吗?(不对啊,dosbox还能出事?)
其实都不是,这里我们要好好地思考一下offset的工作原理是什么?
就是——在程序在被编译加载到内存的时候,系统就会读出标号的偏移地址,然后将“offset 某某标号”替换为标号的偏移地址,所以你知道为什么了吗?
那个mov si,0030是怎么来的?
就是我这个代码加载程序在开始运行时,我这句 a:db "OVERFLOWER!!!",0 所在的偏移地址,但实际上在代码加载程序结束后,这段代码被移植到0000:0200上了,那个时候这个 a:db"OVERFLOWER!!!",0的偏移地址是0020h,也就是说这句 offset 所记录的地址 “失效了” 。
offset并不是一个实时运行的指令,仅仅是一个替换符,类似于C语言的#define一样,在编译的时候就已经执行了,就替换好了,而不是说在程序执行到这一步时才开始“大显神通”。
所以这个程序怎么改? 没什么招了,只能改为mov si,202h 了。
所以通过这次“塔塔开”,我们对offset这个语句有了更加清楚了认知——如果你的程序所在的地址在途中不会发生改变,那就请尽情的使用offset吧,这是一个非常实用的助记码,但是,如果你的程序所在入口地址会发生改变,那么就请你还是老老实实地用“人工智能”的方法来判断你的地址吧。
T * 的!我觉得这时但凡会点编译原理,分分钟解决,可惜我不会,一顿瞎心思,最后在学日语的时候突然灵光一现,才解决这个问题。
所以底层的东西还是很重要的,老子说过“大道至简”,计算机专业“术”实在是太多了,一个一个学那简直就是要累死人,所以我认为我们应该适当地多掌握一些“道”,懂一些底层内在的东西,才可在这个的时代不会那么的迷茫。
附上这个程序的源码:(汇编器为NASM)
assume cs:code,ss:stake
stake segment
dw 16 dup (0)
stake ends
code segment
start: ;功能就是把0号中断改为自己定制的中断程序
mov ax,0
mov es,ax
mov ax,200h
mov di,ax
mov ax,cs
mov ds,ax
mov ax,offset AsaHi
mov si,ax
mov cx,offset CHINA-offset AsaHi
cld
rep movsb
mov ax,0
mov es,ax
mov word ptr es:[2],ax
mov ax,200h
mov word ptr es:[0],ax
mov ax,4c00h
int 21h
AsaHi:
jmp short K
a:db "OVERFLOWER!!!",0
K:
mov ax,0b800h
mov es,ax
mov di,1950d
mov ax,cs
mov ds,ax
mov si,202h ;这个就是出问题的那段代码
BAYUE:
mov cl,byte ptr ds:[si]
mov ch,0
jcxz SUCC
mov byte ptr es:[di],cl
inc di
mov byte ptr es:[di],10011100b
inc di
inc si
jmp short BAYUE
SUCC:nop
mov ax,4c00h
int 21h
CHINA:
code ends
end start
贺利坚老师的汇编语言程序设计课程真的很好,非常的赞!!