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與實際運行的段值是不一樣的。當我進一步詢問怎么得到運行段值時,他說以后再說。(???)
無奈到此作罷。以后可能再進行修改。