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启动时,屏幕清除,没有任何反应。我究竟做错了什么?

(感谢小丑告诉我,我没有说明这个问题。我还是新的堆栈溢出。)

+2

您忘了提及问题所在......此外,bochs有一个内置的调试器,请确保您使用它。 PS:'pusha; pop bx'是不好的练习,可能不会做你认为它的工作(当然你没有写评论你想要做什么) – Jester

+0

我会看看调试器,感谢你的建议。当做'pusha; pop bx'我打算推动所有的增值税进入堆栈,只取出bx。我会尝试推动除bx以外的所有变量,并在完成时弹出它们。 – C317SO

+2

'pop bx'不会从推送的内容中搜索出'bx'的原始值,它只会从堆栈中移除最顶端的项目。由于'pusha'的工作原理,这不会是'bx'。无论如何,'pusha'不会改变'bx',这个值仍然存在,所以你不需要'流行'。 – Jester

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 

不完全知道是什么意思确保修改寄存器当函数是谨慎的,但这个例子确实工作。由于这本质上是代码的副本,所以你只需要记录它,但是有两种可能会被问到的特质。你为什么使用这些指令,为什么它们按照这个顺序。

+0

非常感谢您的回复。我不太清楚你的意思是被捣毁,AX是你的意思? (经过测试,是的!我会在继续阅读之前阅读注册表,我认为小心的意思是不要使用你不懂的寄存器......)另外,我注意到你包含了函数在代码中。我想这是一种优惠的方式(与便利/可访问性和一个二进制文件一起),就像我们在格式化方面的差异一样。再次感谢您的帮助。 – C317SO

+1

@Kohrokho是的,垃圾在这种情况下意味着你​​设置AH = 14,然后在下一条指令中删除它。虽然我同意使用'%include',但我会推荐格式化样式,因为一旦您达到了拥有数千行代码的地步,它确实有所作为。尽管没有争论,不管你怎么做,如果结果是无错代码,并且你很容易维护,那么无论你做得如何,这都很好。 –