装配86 QEMU:致命的:试图执行code以外的RAM或ROM [英] assembly x86 qemu: fatal: Trying to execute code outside RAM or ROM
问题描述
我工作的一个非常基本的壳,唯一的命令是目前的帮助。如果你输入什么不对,你得知命令心不是认可。某处段和堆栈设置我有,shell会吐出一些废话后,我输入任何东西,然后冻结完全的错误。
错误我得到了终端
QEMU:致命的:试图在0xff0fe990执行code以外的RAM或ROM
EAX = 0000ffe0 EBX = 0000FFFF ECX = ff00e990 EDX = 0000e000
ESI = 000001a4 EDI = 0000011e EBP = 00000019 ESP = 0000ffdc
EIP = ff00e990 EFL = 00000002 [-------] CPL = 0 II = 0 A20 = 1 SMM = 0 HLT = 0
ES = B000 000b0000 0000FFFF 00009300
CS = F000 000f0000 0000FFFF 00009b00
SS = E000 000e0000 0000FFFF 00009300
DS = E000 000e0000 0000FFFF 00009300
FS = 0000 00000000 0000FFFF 00009300
GS = 0000 00000000 0000FFFF 00009300
LDT = 0000 00000000 0000FFFF 00008200
TR = 0000 00000000 0000FFFF 00008b00
GDT = 000f6688 00000037
IDT = 00000000 000003ff
CR0 = 00000010 CR2 = 00000000 CR3 = 00000000 CR4 = 00000000
DR0 = 00000000 DR1 = 00000000 DR2 = 00000000 DR3 = 00000000
DR6 = ffff0ff0 DR7 = 00000400
CCS = 00000018 CCD = 0000ffe0 CCO = SUBL
EFER = 0000000000000000
FCW = 037f FSW = 0000 [ST = 0] FTW = 00 = MXCSR 00001f80
FPR0 = 0000000000000000 0000 FPR1 = 0000000000000000 0000
FPR2 = 0000000000000000 0000 FPR3 = 0000000000000000 0000
FPR4 = 0000000000000000 0000 FPR5 = 0000000000000000 0000
FPR6 = 0000000000000000 0000 FPR7 = 0000000000000000 0000
XMM00 = 00000000000000000000000000000000 XMM01 = 00000000000000000000000000000000
XMM02 = 00000000000000000000000000000000 XMM03 = 00000000000000000000000000000000
XMM04 = 00000000000000000000000000000000 XMM05 = 00000000000000000000000000000000
XMM06 = 00000000000000000000000000000000 XMM07 = 00000000000000000000000000000000
compile-and-run.sh:第18行:17015中止陷阱:6 QEMU系统-i386的-s -FDA引导disk.bin -boot一个
我很新的装配,所以我想就如何了解我的错误实在AP preciate指南!
在code下面放置。我用这个脚本运行它,请这样做。
NASM bootloader.asm -o bootloader.bin
DD如果=引导disk.bin BS = 512计数= 2880 =的的/ dev / zero的
DD如果= = bootloader.bin引导disk.bin兑换= notrunc之外
NASM kernel.asm -o kernel.bin
DD如果=的kernel.bin =引导disk.bin兑换= notrunc之外BS = 512寻求= 1
QEMU系统-i386的-s -FDA引导disk.bin -boot一个
bootloader.asm
位16; NASM指令来声明位模式。全球启动
开始:
MOV AX,0x07C0; 07C0 = 1984年,在BIOS查找位置
;引导加载程序的软盘上
MOV DS,AX;设置了数据段(DS)
KERNEL_BLOCK_START EQU 1;开始的地方内核写入磁盘块
KERNEL_BLOCK_SIZE EQU 1;含核块的数量
KERNEL_SEGMENT EQU 1000H;内核将在4096段被加载 调用load_kernel;开始OSload_kernel:
MOV SI,bootloader_status_message
电话bootloader_print_string ;开始从磁盘读取内核字节code
;使用中断13h使用AH = 2H
;选项:AL =扇区读取数
; CH =气缸读取,0到1023
;内缸CL =读取扇区,1-63
; DH =头(0在我们的例子)
; DL =驱动器(也为0)
; ES:BX =缓冲区地址指针
MOV啊,2
MOV人,KERNEL_BLOCK_SIZE
推字KERNEL_SEGMENT
流行ES
异或BX,BX; BX重置为0
MOV CX,KERNEL_BLOCK_START + 1
MOV DX,0
INT 13H;通话中断。写入错误进位标志。 JNC jump_to_kernel;加载成功,进位标志中没有错误 MOV SI,bootloader_load_failed
电话bootloader_print_string
JMP $;永远循环下去jump_to_kernel:
MOV SI,bootloader_load_success
电话bootloader_print_string
JMP KERNEL_SEGMENT:0bootloader_print_string: LODSB;从SI需要一个字节,并将其用于AL(保持指向下一个字节) 还是人,人;所有字符串零结束,以指示该字符串已完成
;我们用它来知道什么时候停止从SI打印字符
;需要本身的逻辑AL或。结果是在进位标志商店 JZ .finish;检查进位标志是零,如果是跳转到结束子程序 ;下面继续打印
MOV啊,0x0E的;对于电传印刷BIOS指令
INT 10H; BIOS中断视频服务。 (AH =电传和放大器; AL =字符) JMP bootloader_print_string;递归调用,直到打印的所有字符 .finish:;完成打印的所有字符
RET;返回到该程序是由所谓的
bootloader_status_message DB'引导装载程序:加载内核...',0X0D,0x0A的,0
bootloader_load_failed DB'引导程序致命的:加载内核失败。回家了。',0X0D,0x0A的,0
bootloader_load_success DB'引导程序:阅读内核成功,现在跳......',0X0D,0x0A的,0 次510 - ($ - $$)分贝0;循环510次,垫空字节
DW 0xAA55将;最后2个字节是55H将0AAh和
kernel.asm
os_initialize_environment:
STACK_SEGMENT EQU 09000h;常规内存顶部,36864
STACK_SIZE EQU 0FFFFH;堆栈长度:64K-1字节
SCREEN_SEGMENT EQU 0b800h;内存细分市场,BIOS写入显示数据
SCREEN_SIZE_COLUMNS EQU 80; 80宽
SCREEN_SIZE_ROWS EQU 25; 25高度
MOV SP,STACK_SEGMENT
MOV SS,SP
MOV SP,STACK_SIZE
推CS
流行DS
推字SCREEN_SEGMENT
流行ES MOV人,0xF的
MOV SI,os_kernel_read_signal
电话os_print_string 调用os_start;开始OS; -------------------------------------------------- --------
;主程序启动
;可用的套路:os_print_string,os_get_user_input,os_compare_string
; -------------------------------------------------- --------
os_start: MOV SI,os_welcome_message;移动欢迎信息输入
电话os_print_string MOV SI,os_alive_signal;移动欢迎信息输入
电话os_print_string JMP shell_begin
; ---------------
;壳牌+命令
; ---------------
shell_cursor DB'> ',0
shell_command_help分贝'帮助',0
shell_error_wrong_command DB输入错误。键入help来获得帮助。',0X0D,0x0A的,0
; ---------------
; OS字符串
; ---------------
os_welcome_message DB'SSOS是一个简单的操作系统。保持低预期。悲观者永远不会失望。,0X0D,0x0A的,0
os_alive_signal DB命令提示符准备,0X0D,0x0A的,0
os_kernel_read_signal DB'内核从引导程序达到了',0X0D,0x0A的,0
os_action_help DB'可用命令:帮助',0X0D,0x0A的,0
os_waiting_for_input DB'请提供以下输入',0X0D,0x0A的,0
; ---------------
;缓冲
; ---------------
缓冲时间128分贝0
; -------------------------------------------------- --------
;常规:开始外壳
; -------------------------------------------------- --------
shell_begin: MOV SI,shell_cursor;打印>光标
电话os_print_string MOV DI,缓冲;移动缓冲输出目的地
调用os_get_user_input;等待用户输入 MOV SI,缓冲;复制用户输入SI MOV DI,shell_command_help
调用os_compare_string;检查,如果用户键入help命令
JC .command_help
;选定的命令帮助(shell_command_help)
.command_help:
MOV SI,os_action_help
电话os_print_string
JMP shell_begin;复位壳
;错误的用户输入(命令无法识别)
.wrong_input_error:
MOV SI,shell_error_wrong_command
电话os_print_string
JMP shell_begin
; -------------------------------------------------- --------
;常规:在SI打印字符串
;输入1 SI:字符串要打印的必须复制到SI
; -------------------------------------------------- --------
os_print_string: LODSB;从SI需要一个字节,并将其用于AL(保持指向下一个字节) ;所有字符串零结束,以指示该字符串已完成
;我们用它来知道什么时候停止从SI打印字符
还是人,人;需要本身的逻辑AL或。结果是在进位标志商店 JZ .finish;检查进位标志是零,如果是跳转到结束子程序 ;下面继续打印
MOV啊,0x0E的;对于电传印刷BIOS指令
INT 10H; BIOS中断视频服务。 (AH =电传和放大器; AL =字符) JMP os_print_string;递归调用,直到打印的所有字符 .finish:;完成打印的所有字符
RET;返回到该程序是由所谓的
; -------------------------------------------------- --------
;常规:从用户获取字符串
;等待用户输入一个完整的字符串,并将其放入缓冲区。
;敏感的退格键和回车键
; 1.输入缓冲区的DI
;输出2.输入字符缓冲区
; -------------------------------------------------- --------
os_get_user_input:
XOR CL,CL; CL将是我们计数器用于跟踪用户已经输入的字符的数目。
;本身进行异或的cl将其设置为零。 MOV SI,os_waiting_for_input
电话os_print_string .get_char_and_add_to_buffer: MOV啊,0;我们使用的BIOS中断16小时来捕获用户输入。
; AH = 0为16小时,它告诉中断读取用户输入的字符的选项
INT 16H;通话中断。商店在AL读取字符 ;退格键监听器
CMP人,0x08的;用户输入比较退格键,并将结果保存在进位标志
JE .backspace_ pressed;如果比较的结果是1,去子程序.backspace_ pressed ;回车键监听器
CMP人,0X0D;比较用户输入回车键
JE .enter_ pressed;到了回车键相应的子程序 ;输入计数器
CMP CL,0x80的;已经在用户输入128个字节吗? (缓冲限制是128个)
JE .buffer_overflow ;用户输入正常字符 ;打印输入
MOV啊,0x0E的;电传打字机模式
INT 10H;打印中断 STOSB;把字符缓冲区
INC CL;增加计数器
JMP .get_char_and_add_to_buffer;递归
; //子程序
.backspace_ pressed:
CMP CL,0;没有任何意义,如果没有输入已进入擦除任何东西
JE .get_char_and_add_to_buffer;忽略退格preSS ;删除缓存最后输入的字符
;当您使用STOSB,MOVSB或类似的功能,系统隐式使用SI和DI寄存器。
十二月二;因此,我们需要递减迪去的最后一个输入字符,并删除它。
MOV字节[二],0;在位置擦除字节[二]
十二月CL;我们的递减计数器 ;从显示屏擦除字符
MOV啊,0x0E的;再次电传打字机模式
MOV人,0x08的;退格字符
INT 10H MOV人,'';空字符打印
INT 10H MOV人,0x08的
INT 10H JMP .get_char_and_add_to_buffer;回到主程序
;回车键pressed。跳转到退出
.enter_ pressed:
JMP .exit_routine
;缓冲区溢出(缓冲区已满)。不要接受任何更多的字符和退出程序。
.buffer_overflow:
JMP .exit_routine
.exit_routine:
MOV人,0;用户输入信号的端
STOSB
MOV啊,为0x0E
MOV人,0X0D;新队
INT为0x10
MOV人的0x0A
INT为0x10 RET;退出全部程序; -------------------------------------------------- --------
;常规:比较两个字符串平等
;等待用户输入一个完整的字符串,并将其放入缓冲区。
;敏感的退格键和回车键
; 1.输入中的String1 SI 2 String2的DI中
;输出1.结果进位标志
; -------------------------------------------------- --------
os_compare_string:
.compare_next_character:;一个循环,通过人物的性格去
MOV人,[SI];专注于SI下一个字节
MOV BL,[二]着眼于二下一字节
CMP AL,BL
JNE .conclude_not_equal;如果不相等,结论和退出 ;我们知道:两个字节是平等的 CMP人,0;为什么我们只是比较两个零?
JE .conclude_equal;如果是的,我们已经到了字符串的结尾。他们是平等的。 ;增量计数器下一循环
INC迪
INC SI
调用.compare_next_character .conclude_equal:
STC;将进位标志(这意味着他们是平等的)
JMP .done
.conclude_not_equal:
CLC;清除进位标志(即它们不相等)
JMP .done .done:
RET
修复了@Jester建议
;引导程序部门的问题
KERNEL_BLOCK_SIZE EQU 21.明显,只是改变来电JMP
2. MOV ES,缓冲;(忽略SCREEN_SEGMENT作为其甚至没有使用)
3.改变外壳逻辑
shell_begin:
MOV DI,缓冲;移动缓冲输出目的地
调用os_get_user_input;等待用户输入
MOV SI,缓冲;复制用户输入SI
MOV DI,shell_command_help
调用os_compare_string;检查,如果用户键入help命令
JC .command_help
JNC .wrong_input_error .command_help:
MOV SI,os_action_help
电话os_print_string
JMP shell_begin;复位壳 .wrong_input_error:
MOV SI,shell_error_wrong_command
电话os_print_string
JMP shell_begin JMP shell_begin
主要的问题是,你kernel.bin已经超越1扇区,而你只载1扇区。
进一步的问题:
- 在
os_compare_string
的呼叫.compare_next_character
应该是JMP
。 - 在
os_get_user_input
,STOSB
使用ES
段,但你已经设置为指向显存,所以它不会存储在缓冲区 输入的文本 - 在
shell_begin
当你比较输入help命令时,code流量会经常去.command_help
I'm working on a very basic shell where the only command currently is 'help'. If you type something wrong, you're informed that the command isnt recognized. Somewhere in the segment and stack setup I have a bug that causes the shell to spit out some nonsense after I type anything and then freeze completely.
Error I get in terminal
qemu: fatal: Trying to execute code outside RAM or ROM at 0xff0fe990
EAX=0000ffe0 EBX=0000ffff ECX=ff00e990 EDX=0000e000
ESI=000001a4 EDI=0000011e EBP=00000019 ESP=0000ffdc
EIP=ff00e990 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =b000 000b0000 0000ffff 00009300
CS =f000 000f0000 0000ffff 00009b00
SS =e000 000e0000 0000ffff 00009300
DS =e000 000e0000 0000ffff 00009300
FS =0000 00000000 0000ffff 00009300
GS =0000 00000000 0000ffff 00009300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 000f6688 00000037
IDT= 00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000018 CCD=0000ffe0 CCO=SUBL
EFER=0000000000000000
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
compile-and-run.sh: line 18: 17015 Abort trap: 6 qemu-system-i386 -s -fda boot-disk.bin -boot a
I'm very new to assembly so I'd really appreciate guides on how to understand my mistake! The code is placed below. I run it with this script, please do the same.
nasm bootloader.asm -o bootloader.bin
dd if=/dev/zero of=boot-disk.bin bs=512 count=2880
dd if=bootloader.bin of=boot-disk.bin conv=notrunc
nasm kernel.asm -o kernel.bin
dd if=kernel.bin of=boot-disk.bin conv=notrunc bs=512 seek=1
qemu-system-i386 -s -fda boot-disk.bin -boot a
bootloader.asm
BITS 16 ; NASM directive for declaring the bit-mode.
global start
start:
mov ax, 0x07C0 ; 07C0 = 1984, the location where BIOS looks for the
; bootloader on the floppy disk
mov ds, ax ; sets up data segment (ds)
KERNEL_BLOCK_START equ 1 ; Starting disk block where kernel is written
KERNEL_BLOCK_SIZE equ 1 ; Number of blocks containing kernel
KERNEL_SEGMENT equ 1000h ; Kernel will be loaded at segment 4096
call load_kernel ; begin OS
load_kernel:
mov si, bootloader_status_message
call bootloader_print_string
; begin reading kernel byte code from disk
; Uses interrupt 13h with AH = 2h
; Options: AL = sectors to read count
; CH = Cylinder to read, 0 to 1023
; CL = Sector within Cylinder to read, 1-63
; DH = Head (0 in our case)
; DL = Drive (also 0)
; ES:BX = Buffer address pointer
mov ah, 2
mov al, KERNEL_BLOCK_SIZE
push word KERNEL_SEGMENT
pop es
xor bx, bx ; reset bx to 0
mov cx, KERNEL_BLOCK_START + 1
mov dx, 0
int 13h ; call interrupt. Writes error to Carry flag
jnc jump_to_kernel ; loading success, no error in carry flag
mov si, bootloader_load_failed
call bootloader_print_string
jmp $ ; loop forever
jump_to_kernel :
mov si, bootloader_load_success
call bootloader_print_string
jmp KERNEL_SEGMENT:0
bootloader_print_string:
lodsb ; Takes one byte from SI and puts it to AL (maintains pointer to next byte)
or al, al ; All strings end with zero to indicate that the string has finished
; we use that to know when to stop printing characters from SI
; takes logical OR of AL by itself. Result is store in Carry Flag
jz .finish ; checks if the carry flag is zero and if so jumps to finish subroutine
; continue printing below
mov ah, 0x0E ; BIOS directive for Teletype printing
int 10h ; BIOS interrupt for video services. (AH=Teletype & AL=character)
jmp bootloader_print_string ; recursive call until all characters are printed
.finish: ; finished printing all characters
ret ; return to where this routine was called from
bootloader_status_message db 'bootloader: loading kernel...', 0x0D, 0x0A, 0
bootloader_load_failed db 'bootloader fatal: loading kernel failed. Go home.', 0x0D, 0x0A, 0
bootloader_load_success db 'bootloader: reading kernel success, jumping now...', 0x0D, 0x0A, 0
times 510 - ($ - $$) db 0 ; loop 510 times and pad with empty bytes
dw 0xAA55 ; last 2 bytes are 55h and 0AAh
kernel.asm
os_initialize_environment:
STACK_SEGMENT equ 09000h ; top of Conventional memory, 36864
STACK_SIZE equ 0ffffh ; stack length: 64K-1 bytes
SCREEN_SEGMENT equ 0b800h ; segment of memory where BIOS writes display data
SCREEN_SIZE_COLUMNS equ 80 ; 80 width
SCREEN_SIZE_ROWS equ 25 ; 25 height
mov sp, STACK_SEGMENT
mov ss, sp
mov sp, STACK_SIZE
push cs
pop ds
push word SCREEN_SEGMENT
pop es
mov al, 0xf
mov si, os_kernel_read_signal
call os_print_string
call os_start ; begin OS
; ----------------------------------------------------------
; Start of main program
; Available routines: os_print_string, os_get_user_input, os_compare_string
; ----------------------------------------------------------
os_start:
mov si, os_welcome_message ; move welcome message to input
call os_print_string
mov si, os_alive_signal ; move welcome message to input
call os_print_string
jmp shell_begin
; ---------------
; Shell + commands
; ---------------
shell_cursor db '> ', 0
shell_command_help db 'help', 0
shell_error_wrong_command db 'Wrong input. Type help for help.', 0x0D, 0x0A, 0
; ---------------
; OS strings
; ---------------
os_welcome_message db 'SsOS is a Simple Operating System. Keep expectations low. The pessimist is never disappointed.', 0x0D, 0x0A, 0
os_alive_signal db 'Command prompt ready', 0x0D, 0x0A, 0
os_kernel_read_signal db 'Kernel reached from bootloader', 0x0D, 0x0A, 0
os_action_help db 'available commands: help', 0x0D, 0x0A, 0
os_waiting_for_input db 'Please provide input below', 0x0D, 0x0A, 0
; ---------------
; Buffer
; ---------------
buffer times 128 db 0
; ----------------------------------------------------------
; Routine: Begins shell
; ----------------------------------------------------------
shell_begin:
mov si, shell_cursor ; print > cursor
call os_print_string
mov di, buffer ; move buffer to destination output
call os_get_user_input ; wait for user input
mov si, buffer ; copy user input to SI
mov di, shell_command_help
call os_compare_string ; checks if user typed help command
jc .command_help
; command help (shell_command_help) selected
.command_help:
mov si, os_action_help
call os_print_string
jmp shell_begin ; reset shell
; wrong user input (command not recognized)
.wrong_input_error:
mov si, shell_error_wrong_command
call os_print_string
jmp shell_begin
; ----------------------------------------------------------
; Routine: Print String in SI
; Input 1. SI: string to be printed must be copied to SI
; ----------------------------------------------------------
os_print_string:
lodsb ; Takes one byte from SI and puts it to AL (maintains pointer to next byte)
; All strings end with zero to indicate that the string has finished
; we use that to know when to stop printing characters from SI
or al, al ; takes logical OR of AL by itself. Result is store in Carry Flag
jz .finish ; checks if the carry flag is zero and if so jumps to finish subroutine
; continue printing below
mov ah, 0x0E ; BIOS directive for Teletype printing
int 10h ; BIOS interrupt for video services. (AH=Teletype & AL=character)
jmp os_print_string ; recursive call until all characters are printed
.finish: ; finished printing all characters
ret ; return to where this routine was called from
; ----------------------------------------------------------
; Routine: Get String from User
; Waits for a complete string of user input and puts it in buffer.
; Sensitive for backspace and Enter buttons
; Input 1. Buffer in DI
; Output 2. Input char in buffer
; ----------------------------------------------------------
os_get_user_input:
xor cl, cl ; CL will be our counter that keeps track of the number of characters the user has entered.
; XORing cl by itself will set it to zero.
mov si, os_waiting_for_input
call os_print_string
.get_char_and_add_to_buffer:
mov ah, 0 ; We use bios interrupt 16h to capture user input.
; AH=0 is an option for 16h that tells the interrupt to read the user input character
int 16h ; call interrupt. Stores read character in AL
; backspace button listener
cmp al, 0x08 ; compares user input to the backspace button, stores result in Carry Flag
je .backspace_pressed ; if the results of the compare is 1, go to subroutine .backspace_pressed
; enter button listener
cmp al, 0x0D ; compares user input to enter button
je .enter_pressed ; go to appropriate subroutine for enter button
; input counter
cmp cl, 0x80 ; Has the user entered 128 bytes yet? (buffer limit is 128)
je .buffer_overflow
; User input is normal character
; print input
mov ah, 0x0E ; Teletype mode
int 10h ; Print interrupt
stosb ; puts character in buffer
inc cl ; increment counter
jmp .get_char_and_add_to_buffer ; recurse
; // Subroutines
.backspace_pressed:
cmp cl, 0 ; no point erasing anything if no input has been entered
je .get_char_and_add_to_buffer ; ignore backspace press
; Delete last input character from buffer
; When you use stosb, movsb or similar functions, the system implicitly uses the SI and DI registers.
dec di ; Therefore we need to decrement di to get to the last input character and erase it.
mov byte[di],0 ; Erases the byte at location [di]
dec cl ; decrement our counter
; Erase character from display
mov ah, 0x0E ; Teletype mode again
mov al, 0x08 ; Backspace character
int 10h
mov al, ' ' ; Empty character to print
int 10h
mov al, 0x08
int 10h
jmp .get_char_and_add_to_buffer ; go back to main routine
; enter button pressed. Jump to exit
.enter_pressed:
jmp .exit_routine
; buffer overflow (buffer is full). Don't accept any more chars and exit routine.
.buffer_overflow:
jmp .exit_routine
.exit_routine:
mov al, 0 ; end of user input signal
stosb
mov ah, 0x0E
mov al, 0x0D ; new line
int 0x10
mov al, 0x0A
int 0x10
ret ; exit entire routine
; ----------------------------------------------------------
; Routine: Compare equality of two strings
; Waits for a complete string of user input and puts it in buffer.
; Sensitive for backspace and Enter buttons
; Input 1. String1 in SI 2. String2 in DI
; Output 1. result in carry flag
; ----------------------------------------------------------
os_compare_string:
.compare_next_character: ; a loop that goes character by character
mov al, [si] ; focus on next byte in si
mov bl, [di] ; focus on next byte in di
cmp al, bl
jne .conclude_not_equal ; if not equal, conclude and exit
; we know: two bytes are equal
cmp al, 0 ; did we just compare two zeros?
je .conclude_equal ; if yes, we've reached the end of the strings. They are equal.
; increment counters for next loop
inc di
inc si
call .compare_next_character
.conclude_equal:
stc ; sets the carry flag (meaning that they ARE equal)
jmp .done
.conclude_not_equal:
clc ; clears the carry flag (meaning that they ARE NOT equal)
jmp .done
.done:
ret
Fixes suggested by @Jester
;bootloader sector problem
KERNEL_BLOCK_SIZE equ 2
1. obvious, just change call to jmp
2. mov es, buffer ;(ignore SCREEN_SEGMENT as its not even used)
3. change shell logic
shell_begin:
mov di, buffer ; move buffer to destination output
call os_get_user_input ; wait for user input
mov si, buffer ; copy user input to SI
mov di, shell_command_help
call os_compare_string ; checks if user typed help command
jc .command_help
jnc .wrong_input_error
.command_help:
mov si, os_action_help
call os_print_string
jmp shell_begin ; reset shell
.wrong_input_error:
mov si, shell_error_wrong_command
call os_print_string
jmp shell_begin
jmp shell_begin
Main problem is that your kernel.bin has grown beyond 1 sector, and you only load 1 sector.
Further problems:
- In
os_compare_string
, thecall .compare_next_character
should be ajmp
. - In
os_get_user_input
,stosb
uses thees
segment, but you have set that up to point to the video memory, so it won't store the entered text in the buffer - In
shell_begin
when you compare the input to the help command, the code flow will always go to.command_help
这篇关于装配86 QEMU:致命的:试图执行code以外的RAM或ROM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!