我用
汇总了以下代码nasm -f bin option
并将其放入软盘映像,然后使用virtualbox运行
我的目标是call print_word
但我怎么能call print_word
来这里?
要学习如何调用额外扇区中的函数,
我将print_word
放入第二个有意图的部门。
提前致谢。
main.asm中:
org 0x7c00
start:
mov ax, 0x0206
mov cx, 0x0002
mov dx, 0x0000
mov bx, 0x7e00
push bx
pop es
mov bx, 0
.try_again:
int 13h
jc .try_again
mov ax, 0xabcd
push ax
jmp 0x7e00
jmp $
times 510 - ($-$$) db 0
dw 0xaa55
more:
%include "./common/print_word.asm"
print_word.asm:
;print_word(word)
print_word:
push bp
mov bp, sp
push word [bp+4]
call print_word_1
push word [bp+4]
call print_word_2
push word [bp+4]
call print_word_3
push word [bp+4]
call print_word_4
mov sp, bp
pop bp
ret
print_word_1:
push bp
mov bp, sp
mov ah, 0x0e
mov byte al, [bp+4]
shr al, 4
cmp al, 0x0a
jl .num
sub al, 0x0a
jmp .char
.num:
add al, '0'
jmp .put
.char:
add al, 'A'
jmp .put
.put:
int 10h
mov sp, bp
pop bp
ret
print_word_2:
push bp
mov bp, sp
mov ah, 0x0e
mov byte al, [bp+4]
shl al, 4
shr al, 4
cmp al, 0x0a
jl .num
sub al, 0x0a
jmp .char
.num:
add al, '0'
jmp .put
.char:
add al, 'A'
jmp .put
.put:
int 10h
mov sp, bp
pop bp
ret
print_word_3:
push bp
mov bp, sp
mov ah, 0x0e
mov byte al, [bp+5]
shr al, 4
cmp al, 0x0a
jl .num
sub al, 0x0a
jmp .char
.num:
add al, '0'
jmp .put
.char:
add al, 'A'
jmp .put
.put:
int 10h
mov sp, bp
pop bp
ret
print_word_4:
push bp
mov bp, sp
mov ah, 0x0e
mov byte al, [bp+5]
shl al, 4
shr al, 4
cmp al, 0x0a
jl .num
sub al, 0x0a
jmp .char
.num:
add al, '0'
jmp .put
.char:
add al, 'A'
jmp .put
.put:
int 10h
mov sp, bp
pop bp
ret
答案 0 :(得分:0)
使用常规CALL指令。你的汇编程序将使用位移而非绝对地址组装一个CALL NEAR。像这样:
mov ax,0xabcd
push ax
call print_word
add sp,2 ;to restore the stack
jmp $
另请注意,在调用print_word routine
,print_word_1
等时,您的print_word_2
无法正常恢复堆栈。您的调用约定要求调用者删除它在堆栈上推送的参数,因此在每个call print_word_N
指令之后,您必须通过发出add sp,2
指令或弹出最后一个堆栈来恢复堆栈元素进入未使用的寄存器。例如,像这样:
由于传递给不同print_word_N例程的值总是相同的,并且您的例程不会更改参数的值,您可以通过假设参数已经在堆栈中的第二个来优化代码大小以及随后的电话:
print_word:
push bp
mov bp, sp
push word [bp+4]
call print_word_1
call print_word_2
call print_word_3
call print_word_4
mov sp, bp
pop bp
ret
BTW:别忘了这是一台小端机器。您正在转换为十六进制并在[ebp+4]
处打印字节,然后在[ebp+5]
处打印字节。这将导致屏幕上显示CDAB
。十六进制数的两个最左边的数字位于[ebp+5]
的字节中,因此您应首先打印它们,然后将数字存储在字节[ebp+4]
。
啊!关于加载扇区:您的错误是您如何考虑加载扇区的块的段和偏移量。您希望在0000:7E00加载下一个扇区,即加载的前512个字节的代码旁边。相反,您将它加载到7E00:0000,这根本不是相同的地址。
更新和修复的代码如下(加载下一个扇区的部分):
org 0x7c00
start:
mov ax, 0 ;segment is 0
mov ds, ax
mov es, ax
.try_again:
mov ax, 0x0201 ;load 1 sector
mov cx, 0x0002 ;located at sector 2
mov dx, 0x0000
mov bx, 0x7e00 ;into 0000:7E00
int 13h
jnc .ok
.errorsector:
mov ax,0 ;reset floppy controller ir error
int 13h
jmp .try_again
.ok:
mov ax, 0xabcd
push ax
call print_word
add sp,2
jmp $