popa和pusha实际上是如何工作的?



我试图从头开始编写一个简单的操作系统,但是我遇到了一个问题。我写了一个简单的程序,遍历一个字符串并将其打印到屏幕上。

print_string:
pusha
cmp byte[bx], 0    
je exit             
mov ah, 0x0e        
mov al, [bx]        
int 0x10            
inc bx              
jmp print_string    

exit: 
mov ah, 0x0e       
mov al, 13          
int 0x10            
mov al, 10          
int 0x10            
popa
ret                 

我将它包含在主文件中。

[org 0x7c00]              
mov bx, hello               
call print_string           
mov bx, hi                 
call print_string          
jmp $                       
%include "print_string.s"   
hello:                  
db "Hello, World!",0     
hi:
db "This is a test.",0
times 510-($-$$) db 0       
dw 0xaa55                   

但是由于某些原因,不打印Hello, World! This is a test.,而是打印Hello World!

当我删除pushapopa从print_string。S并将其放在主文件中,如下所示:

[org 0x7c00]              
mov bx, hello    

pusha          
call print_string 
popa      

mov bx, hi   
pusha               
call print_string   
popa 

jmp $                       
%include "print_string.s"   
hello:                  
db "Hello, World!",0     
hi:
db "This is a test.",0
times 510-($-$$) db 0       
dw 0xaa55                   

它工作得很好。为什么?

在循环中调用print_string,每次迭代都执行pusha。但是对于多个pusha,只有一个popa指令。

每个pusha指令将堆栈指针向下调整,相应的popa指令将堆栈指针向上调整。这些指令需要动态平衡,正如@ErikEidt准确指出的那样。

修复(对本地标签使用.label):

print_string:
pusha
.next_char:
mov al, [bx]        
test al, al
jz .exit             
mov ah, 0x0e        
int 0x10            
inc bx              
jmp .next_char   
.exit: 
...

最新更新