NASM with Bochs - Assembly - 打印字符串
我想打印一个字符串,并且正在使用NASM Assembly,Bochs来运行程序,并且有两个简单文件。我正在做一个非常简单的引导部门来开始学习Assembly。我试图教我自己,并正在使用此PDF: https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf 我正在尝试创建我自己的字符串打印功能。NASM with Bochs - Assembly - 打印字符串
问题:
; Question 4
; Put together all of the ideas in this section to make a self-contained function for printing
; null-terminated strings, that can be used as follows:
;
; A boot sector that prints a string using our function.
;
[org 0x7c00] ; Tell the assembler where this code will be loaded
mov bx, HELLO_MSG ; Use BX as a parameter to our function , so
call print_string ; we can specify the address of a string.
mov bx, GOODBYE_MSG
call print_string
jmp $ ; Hang
%include "print_string.asm"
; Data
HELLO_MSG:
db ’Hello , World!’, 0 ; <-- The zero on the end tells our routine
; when to stop printing characters.
GOODBYE_MSG:
db ’Goodbye!’, 0
; Padding and magic number.
times 510-($-$$) db 0
dw 0xaa55
; For good marks, make sure the function is careful when modifying registers and that
; you fully comment the code to demonstrate your understanding.
我的代码:
bootsect.asm
org 0x7c00 ; Start at boot sector. Allows us to add offset for labels efficiently
mov bx, loading_sys_msg
calltest:
call str_out
;jmp calltest
jmp $ ; Jump forever. Because end of program lol
; Includes
%include "str_out.asm"
; Database Resources
loading_sys_msg:
db 'Loading OIK v0.0.1', 0
; Padding and magic BIOS number.
times 510-($-$$) db 0
dw 0xaa55
`
str_out.asm
;
; String-printing function
;
str_out:
pusha
pop bx
;add bx, 0x7c00 ; Adds current address if boot sect and no org called (not used)
mov ah, 0x0e ; BIOS teletyping for 0x10 interrupt
mov ax, 0x00 ;prep counter
mov al, [bx] ; character to print placed in al (bx address contents)
prnt: ; printing loop
int 0x10 ; interrupt print
add ax, 0x01 ; add to counter for removal afterwards
add bx, 0x01 ; move bx address forward by 1
mov al, [bx] ; character to print placed in al (bx address contents)
cmp al, 0 ; Compare [al -?- 0]
jg prnt ; If greater, jump to print
sub bx, ax ;remove the counter amount
;sub bx, 0x7c00 ;remove address addition if used earlier (not used)
push bx
popa
Bochs的配置:
# Tell bochs to use our boot sector code as though it were
# a floppy disk inserted into a computer at boot time.
floppya: 1_44=boot_sect.bin, status=inserted
boot: a
Bochs启动时,屏幕清除,没有任何反应。我究竟做错了什么?
(感谢小丑告诉我,我没有说明这个问题。我还是新的堆栈溢出。)
str_out
缺少RET指令,但缺少显示的是因为你的垃圾AH
mov ah, 0x0e ; BIOS teletyping for 0x10 interrupt
mov ax, 0x00 ;prep counter
通常我不会举例说明练习,但在这种情况下,您已经做出了合理的努力,并且可以进行一些逻辑处理。
org 0x7c00
mov bx, Msg
call str_out
hlt
jmp $ - 1
str_out: mov ah, 0x0e
prnt: mov al, [bx]
int 0x10
add bx, 0x01
cmp al, 0
jg prnt
ret
Msg: db 'Loading OIK v0.0.1', 0
times 510-($-$$) db 0
dw 0xaa55
不完全知道是什么意思确保修改寄存器当函数是谨慎的,但这个例子确实工作。由于这本质上是代码的副本,所以你只需要记录它,但是有两种可能会被问到的特质。你为什么使用这些指令,为什么它们按照这个顺序。
非常感谢您的回复。我不太清楚你的意思是被捣毁,AX是你的意思? (经过测试,是的!我会在继续阅读之前阅读注册表,我认为小心的意思是不要使用你不懂的寄存器......)另外,我注意到你包含了函数在代码中。我想这是一种优惠的方式(与便利/可访问性和一个二进制文件一起),就像我们在格式化方面的差异一样。再次感谢您的帮助。 – C317SO
@Kohrokho是的,垃圾在这种情况下意味着你设置AH = 14,然后在下一条指令中删除它。虽然我同意使用'%include',但我会推荐格式化样式,因为一旦您达到了拥有数千行代码的地步,它确实有所作为。尽管没有争论,不管你怎么做,如果结果是无错代码,并且你很容易维护,那么无论你做得如何,这都很好。 –
您忘了提及问题所在......此外,bochs有一个内置的调试器,请确保您使用它。 PS:'pusha; pop bx'是不好的练习,可能不会做你认为它的工作(当然你没有写评论你想要做什么) – Jester
我会看看调试器,感谢你的建议。当做'pusha; pop bx'我打算推动所有的增值税进入堆栈,只取出bx。我会尝试推动除bx以外的所有变量,并在完成时弹出它们。 – C317SO
'pop bx'不会从推送的内容中搜索出'bx'的原始值,它只会从堆栈中移除最顶端的项目。由于'pusha'的工作原理,这不会是'bx'。无论如何,'pusha'不会改变'bx',这个值仍然存在,所以你不需要'流行'。 – Jester