2017-01-24 56 views
3

我有一個代碼段位於boot.img文件的扇區37,在我的主引導記錄中,我將這段代碼加載到內存0x5678:0x1234,這是我的彙編代碼:8086彙編:把代碼段開頭的變量區域

[BITS 16]    ;Set code generation to 16 bit mode 

ORG 0x1234  ;set addressing to begin at 0x5678:0x1234 
mov ax, cs 
mov ds, ax 
mov es, ax 



    call cls ;call routine to clear screen 
    call dspmsg ;call routine to display message 

startdt: 
    call date 
    call cvtmo 
    call cvtday 
    call cvtcent 
    call cvtyear 
    call dspdate 

    call time 
    call cvthrs 
    call cvtmin 
    call cvtsec 
    call dsptime 

    jmp startdt ;use infinite loop to halt? 

cls:    
    mov ah,06h ;function 06h (Scroll Screen) 
    mov al, 0 ;scroll all lines 
    mov bh,0x0a ;Attribute (light green on black) 
    mov ch,0 ;Upper left row is zero 
    mov cl,0 ;Upper left column is zero 
    mov dh,24 ;Lower left row is 24 
    mov dl,79 ;Lower left column is 79 
    int 10H ;BIOS Interrupt 10h (video services) 
    ret 

dspmsg: 
    mov ah,13h ;function 13h (Display String) 
    mov al,0 ;Write mode is zero 
    mov bh,0 ;Use video page of zero 
    mov bl,0x0c ;Attribute (light red on black) 
    mov cx,msglen ;Character string is 25 long 
    mov dh,3 ;position on row 3 
    mov dl,[center] ;and column 28 
    lea bp,[msg] ;load the offset address of string into BP 
    int 10H 
    ret 
    msg: db 'Pradox V 0.1 Jiansong He',10,13 
    msglen: equ $-msg 

    int 10H 
    ret 

date: 
;Get date from the system 
mov ah,04h ;function 04h (get RTC date) 
int 1Ah  ;BIOS Interrupt 1Ah (Read Real Time Clock) 
ret 

;CH - Century 
;CL - Year 
;DH - Month 
;DL - Day 

cvtmo: 
;Converts the system date from BCD to ASCII 
mov bh,dh ;copy contents of month (dh) to bh 
shr bh,1 
shr bh,1 
shr bh,1 
shr bh,1 
add bh,30h ;add 30h to convert to ascii 
mov [dtfld],bh 
mov bh,dh 
and bh,0fh 
add bh,30h 
mov [dtfld + 1],bh 
ret 

cvtday: 
mov bh,dl ;copy contents of day (dl) to bh 
shr bh,1 
shr bh,1 
shr bh,1 
shr bh,1 
add bh,30h ;add 30h to convert to ascii 
mov [dtfld + 3],bh 
mov bh,dl 
and bh,0fh 
add bh,30h 
mov [dtfld + 4],bh 
ret 

cvtcent: 
mov bh,ch ;copy contents of century (ch) to bh 
shr bh,1 
shr bh,1 
shr bh,1 
shr bh,1 
add bh,30h ;add 30h to convert to ascii 
mov [dtfld + 6],bh 
mov bh,ch 
and bh,0fh 
add bh,30h 
mov [dtfld + 7],bh 
ret 

cvtyear: 
mov bh,cl ;copy contents of year (cl) to bh 
shr bh,1 
shr bh,1 
shr bh,1 
shr bh,1 
add bh,30h ;add 30h to convert to ascii 
mov [dtfld + 8],bh 
mov bh,cl 
and bh,0fh 
add bh,30h 
mov [dtfld + 9],bh 
ret 

dtfld: db '00/00/0000' 

dspdate: 
;Display the system date 
mov ah,13h ;function 13h (Display String) 
mov al,0 ;Write mode is zero 
mov bh,0 ;Use video page of zero 
mov bl,0x0a;Attribute 
mov cx,10 ;Character string is 10 long 
mov dh,4 ;position on row 4 
mov dl,[center] ;and column 28 
push ds ;put ds register on stack 
pop es ;pop it into es register 
lea bp,[dtfld] ;load the offset address of string into BP 
int 10H 
ret 

time: 
;Get time from the system 
mov ah,02h 
int 1Ah 
ret 

;CH - Hours 
;CL - Minutes 
;DH - Seconds 

cvthrs: 
;Converts the system time from BCD to ASCII 
mov bh,ch ;copy contents of hours (ch) to bh 
shr bh,1 
shr bh,1 
shr bh,1 
shr bh,1 
add bh,30h ;add 30h to convert to ascii 
mov [tmfld],bh 
mov bh,ch 
and bh,0fh 
add bh,30h 
mov [tmfld + 1],bh 
ret 

cvtmin: 
mov bh,cl ;copy contents of minutes (cl) to bh 
shr bh,1 
shr bh,1 
shr bh,1 
shr bh,1 
add bh,30h ;add 30h to convert to ascii 
mov [tmfld + 3],bh 
mov bh,cl 
and bh,0fh 
add bh,30h 
mov [tmfld + 4],bh 
ret 

cvtsec: 
mov bh,dh ;copy contents of seconds (dh) to bh 
shr bh,1 
shr bh,1 
shr bh,1 
shr bh,1 
add bh,30h ;add 30h to convert to ascii 
mov [tmfld + 6],bh 
mov bh,dh 
and bh,0fh 
add bh,30h 
mov [tmfld + 7],bh 
ret 

tmfld: db '00:00:00' 

dsptime: 
;Display the system time 
mov ah,13h ;function 13h (Display String) 
mov al,1 ;Write mode is zero 
mov bh,0 ;Use video page of zero 
mov bl,0x0a;Attribute 
mov cx,8 ;Character string is 8 long 
mov dh,5 ;position on row 5 
mov dl,[center];and column 0 
push ds ;put ds register on stack 
pop es ;pop it into es register 
lea bp,[tmfld] ;load the offset address of string into BP 
int 10H 
ret 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;variables;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
center: db 25 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;end variables;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

我的模擬器DOSBox中,操作系統是lubuntu在Oracle VM虛擬機器上運行,我自己的操作系統是win8的64 通知變量字段在文件的結尾,如果我把這個申請在在我更新了我的DS和ES寄存器之後,我收到了一個問題: cls和dspmsg子程序不起作用 但是,如果我將值更改爲center: db 30或者只是將這個字段在我的代碼末尾,它會工作。 有人可以解釋爲什麼將變量字段放在我的代碼頂部並更改我的標籤值會影響程序的性能嗎?這是否與我的分段寄存器有關?

這裏是我的裝載機:

;bit16     ; 16bit by default 
    org 0x7c00 
    jmp short start 
    nop 
bsOEM db "OS423 v.0.1"    ; OEM String 

start: 

;;load sector into memory & 5678h:1234h 
    mov bx, 0x5678 ;segmented address 
    mov es, bx  ;move segemented address to es 
    mov bx,0x1234  ;base address to bx 

    mov ah, 02  ;function read sectors 
    mov al, 01  ;# of sectors to load 
    mov ch, 00  ;track to read 
    mov cl, 02  ;sector to read 
    mov dh, 00  ;head to read 
    mov dl, 00   ;drive number 

    int 0x13   ;call interrupt 13 

    jmp 0x5678:0x1234  ;jump to memory address 


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;variables;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

msg: db 'Welcome to Pradox OS 0.1! Authored by Jiansong he', 10, 13, '$' 
mlen equ $-msg 

padding times 510-($-$$) db 0  ;to make MBR 512 bytes 
bootSig db 0x55, 0xaa  ;signature (optional) 
+2

假設您沒有顯示的加載程序仍將控制權轉移到0x5678:0x1234,然後它將包含您的數據,而不是要執行的代碼。請注意,'30'恰好是'PUSH DS'的操作碼,它仍然會讓您的代碼正確執行。 PS:學習使用調試器。 – Jester

+0

瞭解,再次感謝你! – paradox

+1

你知道你可以直接在Windows下運行DOSBox。 –

回答

5

如小丑(在你的最後一個問題和我自己)提到的,我強烈建議使用調試器。該評論是:

我建議BOCHS調試引導程序。它有一個命令行調試,理解真正的尋址模式,並可以作爲它們被執行,設置斷點,顯示寄存器看說明書,檢查存儲等

如果你希望看到當你放置center: db 25發生了什麼在代碼頂部,您可以使用NDISASM來轉儲編碼的指令。假設你的第二個階段是仍然dt.bin你可以使用這個命令來獲取二進制進行拆解輸出:

ndisasm -b16 dt.bin 

此命令拆解dt.bin與假設它是16位指令。如果你是放置在center: db 25dt.asm頂部的代碼之前和組裝dt.bin跑上面的命令你會得到這樣的輸出:

00000000 198CC88E   sbb [si-0x7138],cx 
00000004 D88EC0E8   fmul dword [bp-0x1740] 
00000008 2600E8   es add al,ch 
0000000B 3400    xor al,0x0 
0000000D E86600   call word 0x76 

這不是你的代碼期待!那價值25在哪裏?輸出是十六進制。 25位十進制是0x19。如果你檢查第一個指令解碼198CC88E你會看到19是第一個字節。該單字節將指令解碼變爲完全無意義的。

如果將center: db 25更改爲center: db 30,會發生什麼情況?如果您嘗試進行組裝及以上再次使用NDISASM命令你應該看到這一點:

00000000 1E    push ds 
00000001 8CC8    mov ax,cs 
00000003 8ED8    mov ds,ax 
00000005 8EC0    mov es,ax 
00000007 E82600   call word 0x30 

30十進制是0X1E。正如Jester指出0x1e本身就是一個指令push ds。該單字節指令做了一些無用的事情,但之後的所有指令都如您所期望的那樣。當輸出到這樣的二進制文件時,將數據放置在代碼上方使用-f binNASM可能會導致異常問題。出於這個原因,最好將您的數據放在代碼之後,而不會干擾指令解碼。