gpt4 book ai didi

assembly - 尝试通过 int 16h 读取 key 以 VM 重启结束

转载 作者:行者123 更新时间:2023-11-29 07:54:09 24 4
gpt4 key购买 nike

我试图将键盘交互添加到来自 this example 的代码中.考虑以下文件:

Cargo.toml

[package]
name = "kernelhello"
version = "0.0.1"

[dependencies]
bootloader = "0.3.12"

[package.metadata.bootimage]
default-target = "build.json"

build.json

{
"llvm-target": "x86_64-unknown-none",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"arch": "x86_64",
"target-endian": "little",
"target-pointer-width": "64",
"target-c-int-width": "32",
"os": "none",
"executables": true,
"linker-flavor": "ld.lld",
"linker": "rust-lld",
"panic-strategy": "abort",
"disable-redzone": true,
"features": "-mmx,-sse,+soft-float"
}

src/main.rs

// src/main.rs
#![feature(asm)]

#![no_std] // don't link the Rust standard library
#![no_main] // disable all Rust-level entry points

use core::panic::PanicInfo;

/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}


#[no_mangle]
pub extern "C" fn _start() -> ! {
let mut HELLO: &mut [u8] = &mut b"Hello World!".clone();
let vga_buffer = 0xb8000 as *mut u8;

let mut z = 0;
loop {
for (i, byte) in HELLO.iter_mut().enumerate() {
unsafe {
z += 14;
z %= 4000;
*vga_buffer.offset(z + i as isize * 2) = *byte;
*vga_buffer.offset(z + i as isize * 2 + 1) = 0xa;
asm!("mov $$0, %ah\nint $$0x16");
}
}
}
}

不幸的是,尝试执行 bootimage run 时图像卡在重启循环中 - 如果我注释掉 asm! 调用,则不会发生这种情况.这是一个反汇编:

➜  rust-kernel-hello objdump -D -b binary -Mintel,x86-64  -m i386 target/build/debug/bootimage-kernelhello.bin | grep -C5 'ef01'
eef0: 00
eef1: 48 8b 84 24 d0 00 00 mov rax,QWORD PTR [rsp+0xd0]
eef8: 00
eef9: 48 89 84 24 00 01 00 mov QWORD PTR [rsp+0x100],rax
ef00: 00
ef01: 48 8d bc 24 f0 00 00 lea rdi,[rsp+0xf0]
ef08: 00
ef09: e8 72 fe ff ff call 0xed80
ef0e: 48 89 94 24 20 01 00 mov QWORD PTR [rsp+0x120],rdx
ef15: 00
ef16: 48 89 84 24 18 01 00 mov QWORD PTR [rsp+0x118],rax
--
f119: 48 89 04 24 mov QWORD PTR [rsp],rax
f11d: 48 8b 04 24 mov rax,QWORD PTR [rsp]
f121: c6 00 0a mov BYTE PTR [rax],0xa
f124: b4 00 mov ah,0x0
f126: cd 16 int 0x16
f128: e9 d4 fd ff ff jmp 0xef01
f12d: 48 8d 3d cc 0a 00 00 lea rdi,[rip+0xacc] # 0xfc00
f134: e8 07 04 00 00 call 0xf540
f139: 0f 0b ud2
f13b: 48 8d 3d e6 0a 00 00 lea rdi,[rip+0xae6] # 0xfc28
f142: e8 f9 03 00 00 call 0xf540

我做错了什么?

最佳答案

我想更详细地解释一下 zx485 的评论:

我经常看到汇编语言初学者对int (x86)、syscall (MIPS) 或SWI 是什么指令感到困惑(ARM) 确实如此。

实际上,这些指令是一种特殊形式的调用指令:它们调用一些通常位于操作系统中的子例程。

64 位 x86 CPU 有不同的操作模式。其中之一被命名为“实模式”。在此模式下,CPU 只能执行 16 位代码。

可以使用 int 0x16 调用的 BIOS 子例程仅在 PC 以“实模式”运行时有效。

您的程序是 64 位程序(使用了像 rax 这样的寄存器)这一事实告诉我们您的 CPU 没有在实模式下运行。

如果您正在编写自己的操作系统,您可以定义自己的子例程,这些子例程由某些 int 指令调用:

您可以定义一个由 int 0x16 调用的子例程,它读取键盘,另一个由 int 0x10 调用,写入屏幕。

但是,您也可以自由定义 int 0x16 用于写入屏幕,int 0x10 用于操作系统中的硬盘访问。

并且在任何情况下,您都必须自己编写子例程,因为 BIOS 中现有的子例程不能用于“实模式”以外的任何其他操作模式。 (这就是 Ross Ridge 在他的评论中指出的内容。)

关于assembly - 尝试通过 int 16h 读取 key 以 VM 重启结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54725069/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com