Assembly 读取引导扇区redux
好的,轮到我提问了。“我的代码怎么了?”它是一个dos.com文件(x86),用Nasm编写,在引导到FreeDos(不是DosBox)的情况下运行Assembly 读取引导扇区redux,assembly,x86,nasm,boot,Assembly,X86,Nasm,Boot,好的,轮到我提问了。“我的代码怎么了?”它是一个dos.com文件(x86),用Nasm编写,在引导到FreeDos(不是DosBox)的情况下运行 ; nasm -f bin -o readmbr.com readmbr.asm org 100h ; offset where dos will load us section .text mov si, 5 ; retry count read: mov dx, 80h ; drive mov cx, 1 ; segment mov b
; nasm -f bin -o readmbr.com readmbr.asm
org 100h ; offset where dos will load us
section .text
mov si, 5 ; retry count
read:
mov dx, 80h ; drive
mov cx, 1 ; segment
mov bx, buffer
mov ax, 201h ; read 1 sector
int 13h
jnc goodread
mov ah, 0 ; reset drive
int 13h
dec si
jnz read
jmp exit
goodread:
mov si, buffer
mov cx, 512
top:
lodsb
aam 16
xchg al, ah
call printhex
xchg al, ah
call printhex
mov al, ' '
int 29h
loop top
exit:
int 20h
;mov ah, 4Ch
;int 21h
; ret
printhex:
cmp al, 9
jbe not_alpha
add al, 7
not_alpha:
add al, '0'
int 29h ; print the character in al
ret
section .bss
buffer resb 512
; nasm f-bin -o readmbr.com readmbr.asm
org 100h
section .bss
buffer resb 512
section .text
; completely meaningless interrupt!
mov dl, 13
mov ah, 2
int 21h
mov dx, 80h ; drive
mov cx, 1 ; sector (not "segment", idiot)
mov bx, buffer
mov ax, 201h ; read one sector
int 13h
jc exit
; dump 512 bytes as hex, and ascii (if printable), 16 at a time
mov si, buffer
mov di, 32 ; loop counter
dumpem:
call dump16
dec di
jnz dumpem
exit:
ret
;------------------
;--------------------
; print character in al to stdout
; returns: nothing useful
printchar:
push ax
push dx
mov dl, al
mov ah, 2
int 21h
pop dx
pop ax
ret
;------------------
;--------------------
dump16:
; prints 16 bytes pointed to by si, as hex and as ascii (if printable)
; returns: si pointed to next byte. ax, cx trashed.
mov cx, 16
push si ; save it for the ascii part
top:
lodsb ; al <- [si], inc si
aam 16 ; split al into ah and al - four bits per
xchg al, ah ; we want the high one first
cmp al, 9
jbe not_alpha
add al, 7 ; bump 10 - 15 up to 'A' - 'F'
not_alpha:
add al, '0'
call printchar
xchg al, ah ; swap 'em back and print low nibble
cmp al, 9
jbe not_alpha2
add al, 7
not_alpha2:
add al, '0'
call printchar
mov al, ' '
call printchar
loop top
mov al, '|'
call printchar
mov al, ' '
call printchar
pop si ; get back pointer to 16 bytes
mov cx, 16
asciitop:
lodsb
cmp al, 20h ; we don't want to print control characters!
jae printable
mov al, '.'
printable:
call printchar
loop asciitop
; and throw a CR/LF
mov al, 13
call printchar
mov al, 10
call printchar
ret
;--------------------
当我在调试器(FreeDos’DEBUG)中单步执行此操作时,我得到的是预期的输出(或多或少),但不是“程序正常终止”,而是“意外的单步断点”(或类似的断点),ip
表示我“陷入了困境”。当我试图以“高速”运行它时,它会挂起机器,根本没有输出!Dos的靴子现在很快就穿上了,但过了一段时间它还是会变老。我想是时候让其他人看看了
我意识到我做了一些“不太好记录”的事情-aam16
和int29h
例如-但是这些事情“过去对我来说很有用”。。。并且似乎在调试器中工作。我在做什么使机器挂起(根本没有输出)
埃米特,如果你这么想的话,告诉我这在DosBox里有什么作用。其他人,谢谢你的帮助
编辑:好的。。。我“修复”了它。我不知道怎么做!使用“完全无意义的中断”,它可以工作。没有它,结果和以前一样-挂起而没有输出。显然,FreeDos不喜欢int13h
作为第一个中断(?)。不知道为什么。我不记得以前见过这样的事。这个版本有一个稍微好一点的hexdump,也包括ascii,这应该可以更容易地判断您是否正在查看一个真正的引导扇区。我有一个想法,它不会在DosBox中工作。。。这使得整个练习毫无意义
; nasm -f bin -o readmbr.com readmbr.asm
org 100h ; offset where dos will load us
section .text
mov si, 5 ; retry count
read:
mov dx, 80h ; drive
mov cx, 1 ; segment
mov bx, buffer
mov ax, 201h ; read 1 sector
int 13h
jnc goodread
mov ah, 0 ; reset drive
int 13h
dec si
jnz read
jmp exit
goodread:
mov si, buffer
mov cx, 512
top:
lodsb
aam 16
xchg al, ah
call printhex
xchg al, ah
call printhex
mov al, ' '
int 29h
loop top
exit:
int 20h
;mov ah, 4Ch
;int 21h
; ret
printhex:
cmp al, 9
jbe not_alpha
add al, 7
not_alpha:
add al, '0'
int 29h ; print the character in al
ret
section .bss
buffer resb 512
; nasm f-bin -o readmbr.com readmbr.asm
org 100h
section .bss
buffer resb 512
section .text
; completely meaningless interrupt!
mov dl, 13
mov ah, 2
int 21h
mov dx, 80h ; drive
mov cx, 1 ; sector (not "segment", idiot)
mov bx, buffer
mov ax, 201h ; read one sector
int 13h
jc exit
; dump 512 bytes as hex, and ascii (if printable), 16 at a time
mov si, buffer
mov di, 32 ; loop counter
dumpem:
call dump16
dec di
jnz dumpem
exit:
ret
;------------------
;--------------------
; print character in al to stdout
; returns: nothing useful
printchar:
push ax
push dx
mov dl, al
mov ah, 2
int 21h
pop dx
pop ax
ret
;------------------
;--------------------
dump16:
; prints 16 bytes pointed to by si, as hex and as ascii (if printable)
; returns: si pointed to next byte. ax, cx trashed.
mov cx, 16
push si ; save it for the ascii part
top:
lodsb ; al <- [si], inc si
aam 16 ; split al into ah and al - four bits per
xchg al, ah ; we want the high one first
cmp al, 9
jbe not_alpha
add al, 7 ; bump 10 - 15 up to 'A' - 'F'
not_alpha:
add al, '0'
call printchar
xchg al, ah ; swap 'em back and print low nibble
cmp al, 9
jbe not_alpha2
add al, 7
not_alpha2:
add al, '0'
call printchar
mov al, ' '
call printchar
loop top
mov al, '|'
call printchar
mov al, ' '
call printchar
pop si ; get back pointer to 16 bytes
mov cx, 16
asciitop:
lodsb
cmp al, 20h ; we don't want to print control characters!
jae printable
mov al, '.'
printable:
call printchar
loop asciitop
; and throw a CR/LF
mov al, 13
call printchar
mov al, 10
call printchar
ret
;--------------------
;nasm f-bin-o readmbr.com readmbr.asm
组织100小时
第2节bss
缓冲区resb512
第节.案文
; 完全没有意义的打断!
mov dl,13
mov啊,2
int 21h
mov-dx,80h;开车
mov-cx,1;部门(不是“部门”,傻瓜)
缓冲区
mov ax,201h;读一个扇区
int 13h
jc出口
; 将512字节转储为十六进制和ascii(如果可打印),每次16字节
缓冲区
莫夫迪,32岁;循环计数器
dumpem:
呼叫dump16
德克迪
jnz dumpem
出口:
ret
;------------------
;--------------------
; 将al中的字符打印到标准输出
; 返回:没有什么有用的
打印字符:
推斧
推送dx
mov dl,al
mov啊,2
int 21h
波普dx
爆斧
ret
;------------------
;--------------------
第16段:
; 以十六进制和ascii格式打印si指向的16个字节(如果可打印)
; 返回:si指向下一个字节。斧头,残废了。
莫夫cx,16
推硅;将其保存为ascii部分
顶部:
lodsb;al
查找在dosbox环境中运行的代码的附加输出。我想在这里提出一个有趣的观点,当我将int29h替换为int10h/ah=0x0e时,输出是不同的,十六进制值已经改变了
好的。这是Linux版本的输出(比重新启动容易)。它“包裹”得很恐怖,但你可以看到它是“LILO”
FA EB 21 01 B2 01 4C 49 4C 4F 16 07 80 60 FC 47||ë!。².利洛.`G
00 00 00 00 FA 9A FA 47 40 F6 3F 30 81 00 80 60|…|úG@ö0`
16 2B F3 01 B8 C0 07 8E D0 BC 00 08 FB 52 53 06 |¸Àм..RS。
56 FC 8E D8 31 ED 60 B8 00 12 B3 36 CD 10 61 B0|Vü216; 1í184;…³6Ía°
0D E8 64 01 B0 0A E8 5F 01 B0 4C E8 5A 01 60 1E||d.°LèZ.`。
07 80 FA FE 75 02 88 F2 BB 00 02 8A 76 1E 89 D0|þu.ò»v.Ð
80 E4 80 30 E0 78 0A 3C 10 73 06 F6 46 1C 40 75||ä0áx.“告诉我这在DosBox中有什么作用”:它打印一屏00。@Frank我现在没有访问我的DosBox的权限,一旦我有了它,我会告诉你的。@Frank刚刚找到这个链接,它使用aam16以十六进制打印,但不确定它对你有什么用处。嗨Frank,当我在DosBox中运行这个程序时,我可以看到hextump,我的意思是Hex值,但我如何才能确保它是我的硬盘引导扇区,我必须检查最后2个字节,其中包含签名值,将附加在我的Dosbox的屏幕截图中answer@Frank我试着把这些十六进制值解码成ascii码,看起来像是,它在打印你给出的代码,这就是这里所期望的吗?像个白痴一样,我忘了在我的“标签”中加上“组装”。谢谢你修好了,不管是谁做的。我是新来的,我能说什么?既不是全零,也不是发布的屏幕快照看起来像引导扇区。“DosBox”是虚拟的,可能看不到“真实”硬盘。(如果你能写到真正的硬盘上,就会严重违反安全!)我会重新启动到FreeDos,然后再试一次,这次不要那么“聪明”。)对我来说编写Linux程序更容易——完全不同的方法。我会再打给你的。感谢所有到目前为止的反馈@FrankKotler您是否可以将MBR的O/P连接到此处谢谢Frank,看起来我在这里运气不好,因为在运行Linux版本的时,我只能看到黑屏code@AmitSinghTomar好的,Linux版本,如果您在运行后立即键入echo$?
,应该会打印一个错误号。13是我得到的最常见的一个——拒绝许可。这意味着我忘记了以root用户身份运行它,或者按照注释中的描述“烹饪”文件。2-无此类文件,6-无此类设备或地址,19-无此类设备。如果有必要,可以在errno.h中查找。如果它说0,我的代码就是错误。我认为判断您从哪个设备启动最简单的方法是键入df
,然后查看“/”上安装了什么。勇气!fbkotler@myfairpoint.netHI弗兰克,我按照你的建议做了,echo$,输出结果为2意味着没有这样的文件,df的输出显示/dev/loop0挂载在“/”上。我应该如何理解它,/dev/loop0看起来不像是从硬盘启动的,或者是吗?我不知道如何理解/dev/loop0。听起来像是“虚拟启动”?如果你使用文件名
,你会得到任何输出吗?非常感谢你,弗兰克。最后我想我可以看到硬盘的引导扇区了,我把文件名改成了/dev/sda3,它安装在/host上,把文件名改成/dev/loop0会给我带来很多0。我已经附上了linux版本的co的输出