assembly - 无法在保护模式下打印
问题描述
我在操作系统开发链接1链接2中关注这些 教程
我无法在保护模式下打印。
这是我的代码:
$ gcc -E boot.S
# 1 "boot.S"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "boot.S"
# 1 "header.h" 1
read_fail:
.asciz "Disk read failed"
.altmacro
.macro PUSHA
push %ax
push %bx
push %cx
push %dx
.endm
.macro POPA
pop %ax
pop %bx
pop %cx
pop %dx
.endm
.macro PUSH_EA
push %eax
push %ebx
push %ecx
push %edx
.endm
.macro POP_EA
pop %eax
pop %ebx
pop %ecx
pop %edx
.endm
.macro CLEAR
PUSH_EA
mov $0x0600, %ax
mov $0x07, %bh
mov $0x00, %cx
mov $0x184f, %dx
int $0x10
CURSOR_POS
POP_EA
.endm
.macro CURSOR_POS x=2, y=2
PUSH_EA
mov $0x02, %ah
mov $0x00, %bh
mov \x, %dh
mov \y, %dl
int $0x10
POP_EA
.endm
.macro BEGIN
.code16
_start:
xor %ax,%ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
mov %ax, %bp
mov %bp, %sp
.endm
.macro PRINT_STRING str
LOCAL loop,end
mov \str, %si
mov $0x0E, %ah
cld
loop:
lodsb
cmp $0x00, %al
je end
int $0x10
jmp loop
end:
.endm
.macro HEX_NIBBLE reg
LOCAL end, letter
cmp $10, \reg
jae letter
add $'0', \reg
jmp end
letter:
add $0x37, \reg
.endm
.macro HEX c
mov \c, %al
mov \c, %ah
shr $4, %al
HEX_NIBBLE <%al>
and $0x0F, %al
HEX_NIBBLE <%ah>
.endm
.macro PRINT_CHAR c=$0x20
push %ax
mov \c, %al
mov $0x0E, %ah
int $0x10
pop %ax
.endm
.macro PRINT_HEX reg=<%al>
push %ax
HEX <\reg>
PRINT_CHAR <%al>
PRINT_CHAR <%ah>
pop %ax
.endm
.macro RESET_DISK
LOCAL error,end
mov $0x00, %ah
mov $0x80, %dl
int $0x13
jmp end
end:
.endm
.macro STAGE2
LOCAL read_error, end
RESET_DISK
mov $__stage2_nsectors, %al
mov $0x9000, %ebp
mov %ebp, %esp
mov $0x02, %ah
mov $0x0002, %cx
mov $0x80, %dl
mov $0x00, %dh
mov $0x1000, %bx
int $0x13
jc read_error
jmp 1f
read_error:
PRINT_STRING $read_fail
.section .stage2
1:
jmp *(0x1000)
.endm
.macro PROTECTED_MODE
.equ CODE_SEG, 8
.equ DATA_SEG, gdt_data - gdt_start
cli
lgdt gdt_descriptor
mov %cr0, %eax
orl $0x01, %eax
mov %eax, %cr0
ljmp $CODE_SEG, $protected_mode
gdt_start:
gdt_null:
.long 0x00
.long 0x00
gdt_code:
.word 0xFFFF
.word 0x0000
.byte 0x00
.byte 0b10011010
# 220 "header.h"
.byte 0b11001111
# 230 "header.h"
.byte 0x00
gdt_data:
.word 0xffff
.word 0x00
.byte 0x00
.byte 0b10010010
.byte 0b11001111
.byte 0x00
gdt_end:
gdt_descriptor:
.word gdt_end - gdt_start
.long gdt_start
.code32
protected_mode:
mov $DATA_SEG, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
mov $0x9000, %ebp
mov %ebp, %esp
.endm
vga_current_line:
.long 0
.macro VGA_PRINT_STR str
LOCAL loop,end
PUSH_EA
mov \str, %ecx
mov vga_current_line, %eax
mov $0, %edx
mov $25, %ebx
div %ebx
mov %edx, %eax
mov $160, %edx
mul %edx
lea 0xb8000(%eax), %edx
mov $0x0f, %ah
loop:
mov (%ecx), %al
cmp $0, %al
je end
mov %ax, (%edx)
inc %ecx
addl $2, %edx
jmp loop
end:
POP_EA
incl vga_current_line
.endm
# 2 "boot.S" 2
.section .text
BEGIN
CLEAR
STAGE2
PROTECTED_MODE
VGA_PRINT_STR $str
jmp .
str:
.asciz "Hello"
生成文件
.POSIX:
IMAGE ?= $(FILENAME)
LD ?= ld
LD_SCRIPT ?= linker.ld
HEADER ?=header.h
GAS ?= gcc
CFLAGS ?= -c
QEMU ?= qemu-system-i386
OUT_EXT ?= .bin
all: $(IMAGE)$(OUT_EXT)
$(IMAGE).bin: $(IMAGE).o
$(LD) -T'$(LD_SCRIPT)' --oformat=binary '$<' -o '$@'
$(IMAGE).o : $(IMAGE).S $(HEADER)
$(GAS) -c '$<' -o '$@'
run: $(IMAGE)$(OUT_EXT)
$(QEMU) '$<'
clean:
rm *.o *bin
链接器.ld
OUTPUT_FORMAT("elf32_i386");
SECTIONS
{
. = 0x7c00;
.text : {
__start = .;
*(.text)
. = 0x1FE;
SHORT(0xaa55);
*(.stage2 )
__stage2_nsectors = ABSOLUTE((. - __start)/512);
. = ALIGN(512);
__end = . ;
__end_align_4k = ALIGN(4K);
}
}
我正在使用 qemu 作为模拟器。在 Qemu 中,应该显示“Hello”,但这是输出。
我无法解决这个问题。对此问题的任何指示表示赞赏。
- 注意:当 bx 寄存器在 .macro STAGE2 中设置为 $1f 时代码有效,但我无法找到其原因
解决方案
可能不是你唯一的问题,但你POP_EA
会以相反的顺序从你的PUSH_EA
宏中弹出东西(堆栈是后进先出的),所以不会匹配:
.macro PUSH_EA
push %eax
push %ebx
push %ecx
push %edx
.endm
.macro POP_EA
pop %eax
pop %ebx
pop %ecx
pop %edx
.endm
因为最后推送的是 %edx 而第一个 pop 是 %eax,所以你最终交换了它们。弹出需要以相反的顺序:
.macro POP_EA
pop %edx
pop %ecx
pop %ebx
pop %eax
.endm
推荐阅读
- javascript - 尝试发送组合键击 (Shift RightArrow) 或触发事件 JQ 2.0.3
- r - 从同一数据集的不同变量创建平滑图
- javascript - 节点 mysql.js。如何正确关闭连接
- r - dplyr mutate_if 有多个条件?
- python - 在不同时间满足条件时停止 python for 循环
- python - 'list' 对象没有属性 'title' 尝试打印文本时
- mysql - 全文分数计算时间长
- mongodb - 启动 ApplicationContext 时出错。要显示条件报告,请使用“调试”重新运行您的应用程序
- ios - react-native-firebase notifications().onNotification() 永远不会在 ios 中调用
- php - 如何在 PHP Laravel 中删除除字符“ñ / Ñ”和破折号“-”之外的特殊字符