关于8086汇编语言offset的一些发现

在学习贺利坚老师的汇编语言课程时,其中有一集是“编制中断处理程序”。

(请关注白色画圈的地方)

然后呢我对这个程序进行了一些小小的改进,因为把这个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

贺利坚老师的汇编语言程序设计课程真的很好,非常的赞!!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值