PS:不更实验了。。一来局限性比较大,二来感觉把自己也捐进去了。。从这个实验开始我都忘了要扩展了。。
前排转载一个个人感觉关于org 100h讲解比较详细的博客:https://blog.csdn.net/ruyanhai/article/details/7177904
首先知道内存地址为[段地址:偏移量],而这里打算输出的标识符num1在数据段里,我们可以通过mov ax,num1得到它的偏移量。
因为不能直接显示整个十六进制数,我们通过移位截取地址中的每一位十六进制数,然后转换成ASCII码来逐位输出,具体看代码。如有错误请指正。
;内存地址为[段地址:偏移量],这里输出标识符num1的内存地址 org 100h start: mov ax,cs mov ds,ax mov ss,ax mov ax,0B800h mov es,ax print_address1: ;通过移位得到段地址的每一位十六进制数,然后放到相应位置 dec word[i] mov ax,word[i] cmp ax,-1 ;判断循环是否执行4次(输出4位十六进制数),是则退出循环 jz mid mov ax,word[i] mov bx,4 mul bx mov cx,ax ;计算要移位的位数,为4*i,然后保存在cx里 mov ax,ds ;ax=ds shr ax,cl ;将ds右移cl位(cl依次为12,8,4,0) and al,0fh ;得到要取的某一位十六进制数 or al,30h ;转换成ASCII码 cmp al,58 ;判断是否小于58,小于说明是数字,否则是字母,还要加上7得到正确的ASCII码 jl digit1 add al,07h digit1: mov ah,0x07 ;设置字符属性 mov cx,ax ;把字符存在cx mov ax,3 sub ax,word[i] mov ax,ax mov bx,2 mul bx mov bp,ax ;计算地址,为[es:(3-i)*2] mov [es:bp],cx jmp print_address1 mid: mov [es:8],byte ':' mov [es:9],byte 0x07 mov word[i],4 print_address2: ;通过移位得到偏移量的每一位十六进制数,然后放到相应位置 dec word[i] mov ax,word[i] cmp ax,-1 ;判断循环是否执行4次(输出4位十六进制数),是则退出循环 jz end mov ax,word[i] mov bx,4 mul bx mov cx,ax ;计算要移位的位数,为4*i,然后保存在cx里 mov ax,num1 ;ax=num1的地址偏移量 shr ax,cl ;将ds右移cl位(cl依次为12,8,4,0) and al,0fh ;得到要取的某一位十六进制数 or al,30h ;转换成ASCII码 cmp al,58 jl digit2 ;判断是否小于58,小于说明是数字,否则是字母,还要加上7得到正确的ASCII码 add al,07h digit2: mov ah,0x07 ;设置字符属性 mov cx,ax ;把字符存在cx mov ax,3 sub ax,word[i] mov ax,ax mov bx,2 mul bx mov bp,ax add bp,10 ;计算地址,为[es:(3-i)*2+10] mov [es:bp],cx jmp print_address2 end: mov [es:18],byte 'H' mov [es:19],byte 0x07 jmp $ datadef: num1 dw 1234h i dw 4 num2 dw 075Ah
得到的地址如下:(注意改代码会导致输出不同,因为每条指令的机器码大小可能不一样)
现在怎么证明输出的内存地址是正确的呢?我们开gdb模式看一下:
可以看到,num1为1234h,此时存储在075A:01AB的位置,对比输出知道偏移量是没问题的,但为什么段地址不对呢?改了很久未果,询问老师得到回复说在DosBox中debug与实际运行的段值是不一样的。当我进一步询问怎么得到运行段值时,他说以后再说。(???)
无奈到此作罢。以后可能再进行修改。