NASM 引导加载程序中的 jmp $

2023-12-01

我试图编写引导加载程序引导装载程序。写的代码是

BITS 16

start:
    mov ax, 07C0h       ; Set up 4K stack space after this bootloader
    add ax, 288     ; (4096 + 512) / 16 bytes per paragraph
    mov ss, ax
    mov sp, 4096

    mov ax, 07C0h       ; Set data segment to where we're loaded
    mov ds, ax


    mov si, text_string ; Put string position into SI
    call print_string   ; Call our string-printing routine

    jmp $           ; Jump here - infinite loop!


    text_string db 'This is my cool new OS!', 0


print_string:           ; Routine: output string in SI to screen
    mov ah, 0Eh     ; int 10h 'print char' function

.repeat:
    lodsb           ; Get character from string
    cmp al, 0
    je .done        ; If char is zero, end of string
    int 10h         ; Otherwise, print it
    jmp .repeat

.done:
    ret


    times 510-($-$$) db 0   ; Pad remainder of boot sector with 0s
    dw 0xAA55       ; The standard PC boot signature

我不明白的是我们为什么要写 jmp$.通过写入jmp$,它进入无限循环。所以,进入无限循环后,最后两行

times 510-($-$$) db 0   ; Pad remainder of boot sector with 0s
    dw 0xAA55       ; The standard PC boot signature

永远不会被执行。

此外,为什么我们要在 ax 上添加 288?


$是当前指令的地址,所以jmp $正在循环自身。这通常是针对致命错误而执行的。

这里,加载器是不完整的,所以它输出一条消息然后循环。 “循环”指令[希望]将被真正的代码[待添加]取代。

定义的事物db or dw伪操作是定义data并且是not可执行指令[通常——除非您需要汇编器未知的特殊指令]。

因此,如果没有无限循环,您将尝试执行以下位置的数据text_string:,这会产生未定义/意外的结果,更不用说尝试执行引导块的最后部分了。


The 288抵消 ...

引导加载到地址0x07C00。它正在尝试在位置设置其堆栈段(0x07C00 + 4096 + 512) --> 0x8E00。但是,它试图将其放入段寄存器中,因此该值必须右移 4 位。0x07C0 is already转移和288 is (4096 + 512) >> 4 or 0x0120。最终值为SS is 0x07C0 + 0x0120 --> 0x08E0[在地址0x8E00]

这似乎是错误的(即算术不匹配),但是sp寄存器设置为4096,所以最后的安息地ss:sp是地址0x9E00.

在8086实模式寻址中,所有地址都使用段寄存器和一些偏移量。最终地址为:address = (segreg << 4) + offset。这是由硬件在以某种方式访问​​内存的每条指令上完成的。

当你在代码中跳转时,你可以使用CS[代码段]寄存器。数据访问使用DS[数据段]寄存器。和堆栈访问(例如push/pop or %sp相对,使用SS[堆栈段]寄存器。还有一个ES[额外段] 字符串指令中使用的寄存器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NASM 引导加载程序中的 jmp $ 的相关文章

  • 破坏/分解函数的函数

    我以前有过 here https stackoverflow com questions 4920610 c class function in assembly 已经表明 C 函数不容易用汇编表示 现在我有兴趣以一种或另一种方式阅读它们
  • 遍历内存编辑每个字节

    我正在编写汇编代码 提示用户输入一串小写字符 然后输出包含所有大写字符的相同字符串 我的想法是迭代从特定地址开始的字节 并从每个字节中减去 20H 将小写变为大写 直到到达具有特定值的字节 我对 Assembly 相当缺乏经验 所以我不确定
  • 这段汇编语言代码是什么意思?

    我是一名学生 刚刚开始学习汇编语言 为了更好地理解它 我只是用 C 写了一个简短的代码并将其转换为汇编语言 奇怪的是我有点听不懂 代码是 include
  • orpd等SSE2指令有什么意义?

    The orpd指令是 压缩双精度浮点值的按位逻辑或 这不是做完 全相同的事情吗por 按位逻辑或 如果是这样 拥有它还有什么意义呢 请记住 SSE1orps https www felixcloutier com x86 orps首先 实
  • 为什么不能执行 mov [eax], [ebx] [重复]

    这个问题在这里已经有答案了 我可以做这个 mov eax ebx 和这个 mov eax ebx 甚至这个 mov eax ebx 但不是这个 错误C2415 mov eax ebx 只是wtf 为什么 它与 ptr1 ptr2 相同 为什
  • 如何在汇编语言中换行打印多个字符串

    我试图在汇编中的不同行上打印多个字符串 但使用我的代码 它只打印最后一个字符串 我对汇编语言非常陌生 所以请耐心等待 section text global start start mov edx len mov edx len1 mov
  • 汇编基础知识:输出寄存器值

    我刚刚开始学习汇编语言 我已经陷入了 在屏幕上显示存储在寄存器中的十进制值 的部分 我使用 emu8086 任何帮助将不胜感激 model small Specifies the memory model used for program
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • 普通的 x86 或 AMD PC 是直接从 ROM 运行启动/BIOS 代码,还是先将其复制到 RAM? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我知道现代计算机已经修改了哈佛架构 它们可以从保存数据的地方以外的地方读取指令 这一事实是否允许它们直接从 ROM 芯片获取指令 他们是先
  • 两个基本的 ANTLR 问题

    我正在尝试使用 ANTLR 来获取简单的语法并生成汇编输出 我在 ANTLR 中选择的语言是 Python 许多教程看起来非常复杂或详细阐述与我无关的事情 我真的只需要一些非常简单的功能 所以我有两个问题 将值从一个规则 返回 到另一规则
  • 为什么当大小大于 50 时,该程序花费的时间会呈指数级增长?

    所以我正在为类编写一个 ARM 汇编快速排序方法 我对大部分内容都有了解 除了复杂性没有意义 我们将其与我们制作的另一种冒泡排序方法进行比较 它对于具有 1 个参数和 10 个参数的示例表现更好 然而 我什至无法比较 100 个参数测试 因
  • 如何知道寄存器是否是“通用寄存器”?

    我试图了解寄存器必须具备什么标准才能被称为 通用寄存器 我相信通用寄存器是一个可以用于任何用途的寄存器 用于计算 将数据移入 移出等 并且是一个没有特殊用途的寄存器 现在我读到了ESP寄存器是通用寄存器 我猜是ESP寄存器可以用于任何事情
  • ARMv8 A64 汇编中立即值的范围

    我的理解是 ARMv8 A64 汇编中的立即参数可以是 12 位长 如果是这样的话 为什么这行汇编代码是 AND X12 X10 0xFEF 产生此错误 使用 gcc 编译时 Error immediate out of range at
  • 如何在 Debian 上编译 DOS 程序?

    在我的汇编语言课程中 我们使用 DPMI 编写 DOS 程序 不幸的是 我无法一直使用 32 位 Windows 机器 我在我使用的几乎每台计算机上都安装了 Debian 虚拟机 我已经安装了 DOSBox 和 DOSEMU 有什么办法可以
  • 为什么如果内存组织为字,则程序计数器加 1;如果内存组织为字节,则程序计数器加 2?

    如果在计算机中一条指令是 16 位 并且如果存储器被组织为 16 位字 则通过在当前指令的地址中加 1 来计算下一条指令的地址 如果内存是按字节组织的 可以单独寻址 那么我们需要在当前指令地址上加二 得到顺序执行的下一条指令的地址 为什么会
  • 如何将 x86 GCC 风格的 C 内联汇编转换为 Rust 内联汇编?

    我在 C 中有以下内联汇编 unsigned long long result asm volatile byte 15 byte 49 shlq 32 rdx orq rdx rax a result rdx return result
  • 如何使用movntdqa避免缓存污染?

    我正在尝试编写一个 memcpy 函数 该函数不会将源内存加载到 CPU 缓存中 目的是避免缓存污染 下面的 memcpy 函数可以工作 但会像标准 memcpy 一样污染缓存 我正在使用带有 Visual C 2008 Express 的
  • linux x86 汇编语言 sys_read 调用的第一个参数应为 0 (stdin)

    我正在编写一个简单的汇编程序来从标准输入读取 如 scanf 这是我的代码 section bss num resb 5 section txt global start start mov eax 3 sys read mov ebx 0
  • 为什么 FMA _mm256_fmadd_pd() 内在函数有 3 个 asm 助记符:“vfmadd132pd”、“231”和“213”?

    有人可以向我解释一下为什么融合乘法累加指令有 3 种变体 vfmadd132pd vfmadd231pd and vfmadd213pd 而只有一个 C 内在函数 mm256 fmadd pd 为了简单起见 在 AT T 语法中 有什么区别
  • 是否可以在VM内使用VMX CPU指令?

    VM guest 内部的进程是否有可能使用 VMX AMD V VT x CPU 指令 然后由外部 VMM 处理而不是直接在 CPU 上处理 Edit 假设外部VM使用VMX本身来管理其虚拟客户机 即它在Ring 1中运行 如果可能的话 是

随机推荐

  • 使用 $.ajax 调用服务器端函数

    最终 我想通过单击按钮将值发送到服务器并查询我的数据库 目前 我在使用 jquery ajax 调用服务器端的函数时遇到问题 这是我的代码
  • PDO fetchObject() 在 fetchall() 之后。返回错误

    我是 PHP 新手 我正在尝试以表格的形式显示员工的详细信息 但while row result gt fetchObject 部分没有执行 因为 result gt fetchObject 返回 false 有什么关系吗 rows res
  • Python:删除除一个for循环之外的所有变量而不受到污染

    reset reset f and reset selective a reset selective f a 是 Matlab 命令 清除所有 的有用 Python 替代品 其中 f 表示 强制而不要求确认 selective 可以与 w
  • Python 3.5 ImportError:动态模块未定义模块导出函数(PyInit_cv2)

    这就是我尝试将 cv2 导入 python3 5 IDLE 时得到的结果 我正在使用 OpenCV 3 1 0 Python3 5 2 Ubuntu 16 04 我尝试了很多安装方法 但没有人解决我的问题 我在终端上进行了导入 但它也停止了
  • 我想捕获所有没有特定标签的标签

    我想捕获我可以使用的所有名为 STRONG 的标签
  • 在响铃期间更改响铃音量

    我想在响铃时更改响铃音量 下面的代码在响铃期间设置它 在系统设置中更改 但它不会在实际响铃时生效 只有下一个响铃呼叫才会使用新值 我可以强制此更改使其立即生效吗 AudioManager audio AudioManager context
  • 在 Java 中通过一次调用(如 JSON.stringify)打印整个结构?

    如何在Java中打印任何类实例 类似于 Javascript 中的 JSON stringify 不需要 JSON 任何格式的输出都可以 public class User public String name password publi
  • PHP旋转和合并时的图像质量问题

    当我合并两个图像作为一个背景 另一个作为目标图像时 我正在使用 png 当我旋转目标图像然后合并时 是的 一切都很好 除了旋转图像的边缘变得锯齿形 我的意思是不平滑 如何使用php GD使边缘平滑 我正在使用的代码
  • 如何公开嵌套在 UserControl 中的控件的 DependencyProperty?

    我正在尝试将图像从窗口绑定到用户控件 显示处理程序 内的用户控件 显示 中 显示有一个 DependencyProperty DisplayImage 这类似于this 但他们的回答对我的问题没有帮助 DisplayHandler 还应该具
  • AppFabric 客户端虚拟机问题

    我们有 AppFabric 缓存集群服务器 我可以使用我的开发计算机作为客户端来使用它 为了模拟不同的Web服务器访问缓存集群服务器 我创建了VMWare虚拟机并安装了Visual Studio 2010和我的Web应用程序 从虚拟机作为客
  • 我可以从 Tomcat 上下文设置 JDBC 隔离级别吗?

    我有一个在 Tomcat 6 中运行的 Web 应用程序 并且我已设法将其配置为使用内置 DBCP 连接池 并且一切都运行良好 但我怀疑它在数据库上的错误隔离级别中运行 我希望它以未提交读的方式运行 但我认为它以已提交读的方式运行 并且不知
  • GtkWindow 一次只能包含一个小部件

    我正在使用此代码来检索并显示来自网络的图像 class Display object def init self self window gtk Window gtk WINDOW TOPLEVEL self window connect
  • 当mapoverlay可见时隐藏mapview ios7

    当 iOS7 中的地图视图顶部有覆盖层时 如何隐藏地图视图 这段代码曾经在 iOS6 中工作 但是当我将我的应用程序升级到 iOS7 时 它停止工作 NSArray views self mapView subviews objectAtI
  • 带有页脚的 Recyclerview 无法删除最后一项

    我在用带页脚的回收视图一切正常 但我无法删除最后一项 假设我们现在列表中有 2 个产品 如果用户删除一个产品 那么 1 个产品将保留在列表中recyclerview那么我无法删除剩余的产品 虽然我有一件商品 但它显示 PACK ID nul
  • C#.Net 中使用 IP 地址和端口号的 TCP/IP 客户端套接字程序

    TCP IP 客户端套接字程序 这里我的主要要求是客户端发送消息 服务器接收消息并存储在 C Net 的数据库表中 使用服务器 IP 地址和端口号 您正在谈论一个简单的服务器 客户端程序 你需要做什么 首先创建一个服务器程序并运行 创建客户
  • 检索文件的全名,按日期过滤

    date datetime 05 19 2014 gci Recurse Select Object FullName LastWriteTime Where Object LastWriteTime ToShortDateString g
  • mod_security:允许没有请求正文的 POST 请求的规则

    我安装了 Apache 2 4 和 mod security 2 9 1 它正在工作 有一些非常基本的规则 我正在尝试发出一个包含一些标头信息的 POST 请求 但请求正文中没有任何内容 该请求是发送给受 mod security 保护的
  • subscribe 的作用是什么?它与 Observable 有何关系?

    我是 Angular 的新手 我遵循的教程有术语 Observable 导师解释了 但我没有完全理解 什么是Observable 以及为什么我们总是要打电话observable subscribe 什么是subscribe 实际上呢 什么是
  • 使用 .NET“异步”API 防止 TIME_WAIT

    我有一个问题 我开发了一个客户端和服务器包装器供我个人使用 但不幸的是由于网络编程知识不足 我在客户端连接期间遇到了 TIME WAIT 问题 我的客户端现在尝试在短时间内与同一主机建立多个连接 我发现其主要原因是因为我试图重用套接字 并且
  • NASM 引导加载程序中的 jmp $

    我试图编写引导加载程序引导装载程序 写的代码是 BITS 16 start mov ax 07C0h Set up 4K stack space after this bootloader add ax 288 4096 512 16 by