ORG指令后设置段寄存器

2024-02-06

我目前正在关注操作系统开发教程 http://brokenthorn.com/Resources/OSDev4.html,其中包括有关引导加载程序的讨论。

我的引导加载程序当前处于 16 位实模式,因此,我能够使用提供的 BIOS 中断(例如 VGA 视频中断等)。

BIOS提供视频中断0x10(即视频电传打字机输出)。视频中断有功能0x0E,它允许我在屏幕上打印一个字符。

这是这个基本的引导加载程序:

org     0x7c00              ; Set program start (origin) address location at 0x7c00.
                            ; This program is loaded by the BIOS at 0x7c00.
bits    16                  ; We live in 16-bit Real Mode.

start:  
        jmp loader

bootmsg     db      "Welcome to my Operating System!", 0        ; My data string.

;-------------------------------------------------------
;   Description:    Print a null terminating string
;-------------------------------------------------------
print:
    lodsb                   ; Load string byte at address DS:SI and place in AL.
                            ; Then, increment/decrement SI as defined by the Direction Flag (DF) in FLAGS.
    or      al, al          ; Set the zero flag - is AL zero?
    jz      printdone       ; Check if this is the null byte
    mov     ah, 0eh
    int     10h
    jmp     print
printdone:
    ret

loader:
    ;|---------- Related to my question ----------|
        xor     ax, ax
        mov     ds, ax
        mov     es, ax
    ;|--------------------------------------------|

    mov     si, bootmsg
    call    print

    cli                     ; Clears all interrupts.
    hlt                     ; Halts the system.

times 510 - ($-$$) db 0    ; Make sure our bootloader is 512 bytes large. 

dw      0xAA55              ; Boot signature - Byte 511 is 0xAA and Byte 512 is 0x55, indicated a bootable disk.1

如上面的代码所示,我突出显示了以下三行:

xor     ax, ax
mov     ds, ax
mov     es, ax

根据原始消息来源,它是这样说的:

设置段以确保它们为 0。请记住,我们有 ORG 0x7c00。这意味着所有地址都基于 0x7c00:0。因为数据段位于同一代码段内,所以 null em。

我有一点困惑。据我了解,org指令告诉加载器在地址处加载该程序0x7c00。那我们为什么不以此作为我们的起始地址呢?这意味着,我们的两个重叠的数据和代码段是not位于一个基地址为零。这基地址应该是 0x7c0。为什么作者把基地址设置为0x0呢?

mov ax, 07c0h
mov dx, ax
mov es, ax

我一直在研究org更多说明和其他文档,我了解发生了什么。

根据NASM 文档 https://www.nasm.us/doc/nasmdoc7.html#section-7.1.1 on the org指令,缩写origin:

ORG指令的功能是指定NASM在程序加载到内存时假定程序开始的起始地址。 [...] NASM 的 ORG 完全按照指令所述执行:起源。它的唯一功能是指定一个偏移量,该偏移量将添加到该节内的所有内部地址引用中。

因此,NASM编译器假设程序将加载到原始指令指定的地址(即org)。 BIOS 正是这样做的。根据下列 https://wiki.osdev.org/Boot_Sequence,一旦 BIOS 找到包含有效引导签名的有效引导扇区,引导加载程序将“加载到内存0x0000:0x7c00处(段0,地址0x7c00)."

从上面的引用来看,当 NASM 文档说“内部地址引用”时,它指的是对代码中使用的具体内存区域的所有引用(例如引用标签等)。例如,上面的引导加载程序代码中的行:mov si, bootmsg将解决bootmsg to 0x07c00 + offset,其中偏移量由字符串的第一个字节的位置确定bootmsg(即“W”)。

使用上面的代码,如果我使用以下命令反汇编 bin 文件ndisasm实用程序 https://www.nasm.us/doc/nasmdoca.html我看到以下内容:

00000000  EB2C              jmp short 0x2e
00000002  57                
00000003  656C              
00000005  636F6D            
00000008  6520746F          
0000000C  206D79            
0000000F  204F70            
00000012  657261            
00000015  7469              
00000017  6E                
00000018  67205379          
0000001C  7374              
0000001E  656D              
00000020  2100              
00000022  AC                lodsb
00000023  08C0              or al,al
00000025  7406              jz 0x2d
00000027  B40E              mov ah,0xe
00000029  CD10              int 0x10
0000002B  EBF5              jmp short 0x22
0000002D  C3                ret
0000002E  31C0              xor ax,ax
00000030  8ED8              mov ds,ax
00000032  8EC0              mov es,ax
00000034  BE027C            mov si,0x7c02
00000037  E8E8FF            call 0x22
0000003A  FA                cli
0000003B  F4                hlt
00000...  ...               ...

(我删除了从0x00000002到0x00000020生成的指令,因为那是我的bootmsg字符串,代表数据,而不是代码)。

正如我们从输出汇编中看到的,在地址 0x00000034 处,我的bootmsg已替换为 0x7c02(例如 0x7c00 + 偏移量=0x02)。

迈克尔·佩奇 https://stackoverflow.com/questions/54045259/setting-segment-registers-after-org-instruction?noredirect=1#comment94930637_54045259也提供了一些非常扎实的见解。认为引导加载程序加载到 0x7c0:0x0000(段 0x07c0,偏移量 0)是一种常见的误解。尽管从技术上讲可以使用这一点,但它已被标准化为使用零段偏移量(一个好的做法是在引导扇区的最开始处强制执行 CS:IP https://wiki.osdev.org/Boot_Sequence)。正如 Michael 所提到的,如果需要更多信息,请查看以下第 4 节段偏移寻址指南 https://thestarman.pcministry.com/asm/debug/Segments.html.

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

ORG指令后设置段寄存器 的相关文章

  • 处理 ARM 芯片的保留寄存器位

    我正在使用 ARM Cortex M3 的寄存器 在文档中 某些位可能是 保留的 我不清楚在寄存器上写入时应该如何处理这些保留位 这些保留位是否可写 我应该小心不要碰它们吗 如果我碰它们 会发生什么不好的事情吗 这是关于如何处理保留位的经典
  • 提高 8086 二进制 -> 格雷码的效率

    我是汇编初学者 这是我设计的代码 用于从二进制转换为灰度 并以十六进制打印生成的位模式 mov al a mov bl al shr bl 1 xor al bl 虽然程序可以运行 但我想了解其他更简单的方法来提高效率 我尝试了很多其他方法
  • 从 C 执行二进制机器代码

    下列的this http www muppetlabs com breadbox software tiny teensy html我已经成功地生成了大小为 528 字节的 a out 当 gcc main c 最初给了我 8539 字节的
  • Hello World 通过一个系统调用打印两条消息?为什么 length equ $-msg1 包括两者? [复制]

    这个问题在这里已经有答案了 section text global start start mov ebx 1 mov eax 4 mov ecx msg1 mov edx len1 int 0x80 mov eax 1 exit mov
  • INT 21h 不打印

    我想知道为什么这个程序不打印 print push ax push bx push dx mov ah 02h ciclo mov al si int 21h inc si loop ciclo pop dx pop bx pop ax r
  • pop eip 指令合法吗?

    我正在参加大学的理论考试 并被问到这个问题 经过一些指令后 esp 增长了 4 eip 增长了 20 该指令可能是什么 我标记了 pop eip 和 ret nasm 32位汇编中是否可以执行pop eip指令 pop eip不是真正的 x
  • 记住 x86-64 System V arg 寄存器顺序的最佳方法是什么?

    我经常忘记系统调用中每个参数需要使用的寄存器 每次我忘记时我都会访问this https stackoverflow com questions 2535989 what are the calling conventions for un
  • Xcode 和 NASM 编码

    如何在 Xcode 中用汇编语言编写和构建程序 我寻找它但没有成功 你能帮助我吗 如果无法在 xcode 中编写 NASM 代码 请推荐一些好的 IDE 自从您提出这个问题以来 这可能已经发生了变化 但目前 安装Xcode 命令行工具 ht
  • 程序集 - 无法设置断点 lldb

    我用这些选项组装了nasm O0 g f macho64但 lldb 抱怨 无法将断点解析到任何实际位置 当我尝试在文件中的行号处设置任何断点时 我已经开始尝试学习 OS X 的 64 位汇编 但到目前为止这确实是一个挑战 似乎几乎没有任何
  • 将 DB 变量中的字节值加载到 16 位寄存器中(符号或零扩展字节)

    我正在使用 MASM 编译器和 DOSBOX 我想将变量的值保存到寄存器中 我想保存num1值转化为cx登记 我怎样才能做到这一点 MODEL SMALL STACK 50H DATA num1 db 5 NL DB 0DH 0AH msg
  • 如何获取变量的地址并在 nasm x86 程序集中取消引用它?

    在c语言中我们使用 获取变量的地址并 取消引用该变量 int variable 10 int pointer pointer variable 汇编中没有变量 variable db A 做几件事 它定义了汇编时间符号variable 就像
  • 使用BIOS int 13h访问不同磁头的扇区

    我的磁盘每磁道有 63 个扇区 根据我的观察 我假设 我想使用 int 13h 读取 16 位引导加载程序上的扇区 例如 如果我想读取扇区号 63 我将执行以下操作 mov dl 0x80 Drive number mov dh 0 Thi
  • 用汇编语言更改 CS:IP

    怎么可以强行改变CS and IP都是汇编语言 ORG指令可用于更改的数量IP 但是你如何改变CS 基本上我想使用汇编来实现多线程 许多论坛 包括堆栈溢出中的一个问题都说这是不可能的 但是即使 C 是由汇编代码制成的 它如何具有多线程选项呢
  • Gas 与 nasm:哪个汇编器生成最好的代码?

    这两种工具都将汇编指令直接翻译成机器代码 但是是否有可能确定哪一个生成最快 最干净的代码 当你用汇编程序编写时 您正在准确地描述生成的指令所以它不依赖于汇编器 这取决于你 您编写的助记符与机器代码中的实际指令之间存在一一对应的关系
  • 为什么使用 mov/cmp 而不是带有两个内存操作数的 cmp? [复制]

    这个问题在这里已经有答案了 我在执行二分搜索程序代码时发现了以下语句 l1 mov si low cmp si high 为什么我们需要将 low 存储在 si 中然后与 high 进行比较 不可以直接写cmp low high 你不能写c
  • 我试图在 AAM 指令之后使用 AX 中存储的值将其除以 2,为什么它不适用于 2 位数字输出?

    英语不是我的母语 请原谅输入错误 我将在此处显示的代码是一项作业 我真的需要了解发生了什么事 我在 DosBox 0 74 和 TASM 汇编器中使用 Intel 8086 语法 当我必须除以 2 时 代码的问题在于三角形的面积 注意 程序
  • 在 REP MOVSW 之前 PUSH CS / POP DS 的目的是什么?

    为什么在下面的代码中我们压入代码段 PUSH CS 然后将其弹出到数据段 POP DS 我将这些行明确指定为 line1 和 line2 请告诉我 MOVSW 在这里是如何工作的 IF HIGHMEMORY PUSH DS MOV BX D
  • 即使我确实为变量设置了初始值,数据段也没有被初始化

    我已经编写了一个代码 该代码应该生成某种数字列表 但是即使我为它们分配了初始值 我的数据段变量也没有被初始化 This is how DS 0000 looks when I run it 这是我的代码 但数据段只保留垃圾值 MODEL s
  • 在 x86 程序集中将整数打印到控制台

    当我在 16 位汇编中添加两个值时 将结果打印到控制台的最佳方法是什么 目前我有这个代码 CODE START mov ax 1 put 1 into ax add ax 2 add 2 to ax current value mov ah
  • NASM 轮班操作员

    您将如何在寄存器上进行 NASM 中的位移位 我读了手册 它似乎只提到了这些操作员 gt gt lt lt 当我尝试使用它们时 NASM 抱怨移位运算符处理标量值 您能解释什么是标量值并举例说明如何使用 gt gt and lt lt 另外

随机推荐

  • 如何从 nuxtjs 服务器中间件获取 POST 数据?

    如何从 nuxtjs 服务器中间件获取 POST 数据 到目前为止 我已经成功地为 GET 做到了这一点 但对于 POST 来说 正文不存在 req body未定义 将其添加到nuxt config js serverMiddleware
  • IPython 笔记本到幻灯片:Reveal 未定义

    我正在使用 nbconvert 从我的笔记本制作一个 Reveal js 幻灯片 具体来说 我正在运行 ipython nbconvert to slides analysis ipynb 这将创建 analysis slides html
  • 发送带有数据库的应用程序

    如果您的应用程序需要数据库并且它带有内置数据 那么发布该应用程序的最佳方式是什么 我是不是该 预先创建 SQLite 数据库并将其包含在 apk 在应用程序中包含 SQL 命令并让它创建数据库并在首次使用时插入数据 我看到的缺点是 可能的
  • 如何将所有路由重定向到 gatsby 索引

    我正在尝试创建一个只有一页来处理所有路线的 Gatsby 项目 我有这样的索引页面 const App gt return
  • 如何将作业放入詹金斯的文件夹中?

    我正在尝试使用 jenkins DSL 脚本将作业放入文件夹中 现在我创建一个 listView 并将我正在使用的代码放入我的工作中 listView MyJobsList jobs map each name it key trim co
  • 如何将一个存储库的公共子文件夹与另一个存储库同步?

    我有一个软件项目foo在我公司托管的内部 GitLab 存储库上 并希望将其部分发布为开源项目baa在 GitHub 上 假设我将公共部分放在 public 文件夹中 foo public 以及文件夹 private 中的私有部分 foo
  • 在列表中查找因素的最有效方法是什么?

    我想要做什么 我需要创建一个函数 给定一个正整数列表 可以有重复的整数 计算所有三元组 列表中 其中第三个数字是第二个数字的倍数 第二个数字是第一个数字的倍数 同一个数字不能在一个三元组中使用两次 但可以被所有其他三元组使用 例如 3 6
  • Bugzilla 如何在本地 PC 上运行?

    我已在本地系统上安装了 bugzilla 版本 3 6 3 当我点击 开设新帐户 按钮 链接并输入有效电子邮件后 我收到以下错误 从 bugzilla daemon 发送邮件到 电子邮件受保护 cdn cgi l email protect
  • 我们是否仍然受制于 Visual Studio 2013 中的安装程序项目 .vdrpoj 或 WiX?

    有没有更好的Installer项目视觉工作室2013 https en wikipedia org wiki Microsoft Visual Studio Visual Studio 2013比安装项目或WiX https en wiki
  • 使用 grep 在多个文件中查找字符串

    我有一个文件夹 里面有子文件夹 所有子文件夹都有多种类型的文件 我想在里面搜索一个单词 css 文件 我正在使用 Windows 7 并且我有grep 我如何使用grep to 找到图案并打印 如果找到模式 请提供文件名 和路径 其实你不需
  • “主要”java.lang.NoClassDefFoundError:org / apache / http / HttpEntity

    我正在尝试在我的项目中使用 apache http 库 我在我的项目中导入了库https i stack imgur com Cm9ck jpg https i stack imgur com Cm9ck jpg 当我运行我的程序时 我收到
  • 在 Razor 组件 (Blazor) 中渲染 Razor 部分视图

    我最近发现了 Blazor 并且一直在尝试一些测试项目 以更好地评估如何将其包含在未来的项目中 由于具有 MVC 背景 我从一个 MVC 项目开始 并向其中添加了 Razor 组件 并将其嵌套在标准 MVC razor 页面中 反过来可能吗
  • Windows 会清除内存页吗?

    我知道 Windows 有一个选项可以清除页面文件当它关闭时 当实际物理 虚拟内存进入或超出范围时 Windows 是否会对实际物理 虚拟内存执行任何特殊操作 例如 假设我运行应用程序 A 它将可识别的字符串写入内存中的变量 然后关闭该应用
  • 使用参数调用事件处理程序

    Visual Studio 2008 C 3 0 我有一个调用事件处理程序的方法 我想将该方法接收到的两个参数传递给事件处理程序 我想做这样的事情 wc DownloadDataCompleted wc DownloadedDataComp
  • 计算进行时显示进度条

    我正在编写代码来计算 Pi 的值 有时可能需要很长时间才能计算 我添加了一个进度条来显示进度 但代码完全按照我的指示执行 它在计算后打开进度条 然后立即关闭它 当值达到 100 时它会关闭 我试图将进度条的代码粘贴到循环中 但很快我意识到这
  • HighcharteR:绘图带和绘图线不起作用

    我正在尝试在 highcharteR 中绘制每日值系列 在图表中标记垂直线 绘图线 和日期周期 绘图带 我研究了几个SO问题并达到了这个脚本 但我发现了以下问题 1 未绘制绘图区 2 未绘制情节 3 x轴应该是以我不理解的方式转换的日期 我
  • FormControl uniqueUntilChanged() 不起作用

    我很难做distinctUntilChanged在下一个场景中工作 我制作了一个异步验证器 它使用服务来检查给定用户名的用户是否存在 该验证器作为指令绑定到输入 class ValidateUniqueUsernameDirective i
  • 可以配置 Tmux 加载 ~/.bashrc 而不是 ~/.bash_profile 吗?

    现在 当我登录 Tmux 时 仅 bash profile被加载 我想要 bashrc改为被呼叫 那可能吗 这个问题与以下无关tmux 要解决它 请确保添加source bashrc to bash profile就是这样 您可以了解更多有
  • dynamoDB - 通过主键数组从数据库获取多个项目

    我有一个用户 id 数组 我想从 dynamoDB 表中获取具有该 id 的所有用户 文档里没找到 有任何想法吗 我最终使用了batchGet 这是一个操作AWS DynamoDB DocumentClient http docs aws
  • ORG指令后设置段寄存器

    我目前正在关注操作系统开发教程 http brokenthorn com Resources OSDev4 html 其中包括有关引导加载程序的讨论 我的引导加载程序当前处于 16 位实模式 因此 我能够使用提供的 BIOS 中断 例如 V