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指令后设置段寄存器 的相关文章

  • 如何通过 $_GET 接受 URL 中的哈希标记?

    据我所知 井号 不会发送到服务器 因此我似乎无法使用原始 PHP 来解析数据 如下面的 URL 所示 index php name Ben address 101 S 10th St Suite 301 我希望使用 GET 数据预先填充表单
  • assembly x86 qemu:致命:尝试在 RAM 或 ROM 之外执行代码

    我正在开发一个非常基本的 shell 其中当前唯一的命令是 help 如果您输入错误 系统会通知您该命令无法识别 在段和堆栈设置的某个地方 我有一个错误 导致 shell 在我输入任何内容后吐出一些废话 然后完全冻结 我在终端中遇到错误 q
  • 如何在不链接libc.so的情况下访问段寄存器?

    我正在尝试在 Ubuntu 20 10 上使用 NASM 版本 2 15 04 在 64 位程序集中编写一个简单的堆栈金丝雀 执行下面的代码会导致在使用命令进行汇编和链接时出现分段错误nasm felf64 canary asm ld ca
  • MIPS 中的影子寄存器是什么以及它们如何使用?

    当我了解 MIPS 架构时 我遇到了影子寄存器 据说它们是通用寄存器的副本 我无法理解以下内容 何时使用影子寄存器 MIPS 影子寄存器用于减少处理中断时的寄存器加载 存储开销 分配了影子寄存器组的中断不需要保存任何现有上下文来提供空闲寄存
  • 无法将 8 位地址移至 16 位寄存器

    我正在尝试分配变量来注册 代码如下 ORG 100h var1 DB 10 var2 DB 20 MOV BX var1 error operands do not match 16 bit register and 8 bit addre
  • 计算段:距绝对地址的偏移量

    我可以计算一个地址Segment Offset as Segment 0x10 Offset 但如何计算相反的情况呢 例如 我怎样才能从0xF4170 to F400 0170和来自0xACF04 to ABCD 1234 您需要具有起始基
  • 为什么我的汇编程序没有将 r1 设置为正确的值?

    我正在 LC3 机器上编写汇编程序 我的汇编程序是一个 LC3 程序 它将 R2 和 R3 相乘并将结果存储在 R1 中 这是我的源代码 带注释 Sets pc to this address at start of program ORI
  • ARM Cortex A8 PMNC 读取在启用后也给出 0.. 有什么想法/建议吗?

    MODULE LICENSE GPL MODULE DESCRIPTION user mode access to performance registers int init arm init void unsigned int valu
  • 汇编语言中的全局_start是什么?

    这是我的汇编级代码 section text global start start mov eax 4 mov ebx 1 mov ecx mesg mov edx size int 0x80 exit mov eax 1 int 0x80
  • 内联 asm 中不支持的指令“mov”将控制寄存器移动到 uint32_t

    我在 C 函数中使用汇编代码 但海湾合作委员会给出unsupported instruction mov 以下代码的错误 uint32 t faulting address asm volatile mov cr2 0 r faulting
  • 寄存器寻址模式与直接寻址模式

    我在试卷中遇到过这个问题 它指出 哪种给定的寻址模式更快 为什么 寄存器寻址方式 直接寻址方式 现在根据我的说法 寄存器寻址模式应该更快 因为寄存器是计算机中最快的存储位置 这是正确答案吗 请帮忙 谢谢 两种寻址模式之间的区别是 地址的来源
  • 如何知道寄存器是否是“通用寄存器”?

    我试图了解寄存器必须具备什么标准才能被称为 通用寄存器 我相信通用寄存器是一个可以用于任何用途的寄存器 用于计算 将数据移入 移出等 并且是一个没有特殊用途的寄存器 现在我读到了ESP寄存器是通用寄存器 我猜是ESP寄存器可以用于任何事情
  • CPU寄存器和多任务处理

    我目前正在学习汇编 我很困惑 CPU 寄存器如何与多任务一起工作 所以在多任务系统中 CPU可以随时暂停某个程序的执行并运行另一个程序 那么在这一步中寄存器值是如何保存的呢 寄存器是压入堆栈还是以其他方式 CPU 寄存器如何与多任务一起工作
  • 在 x86 汇编中将 64 位常量移至内存

    我正在使用 Intel x64 程序集 NASM 编译器 尝试将 0x4000000000000000 常量移至内存 该常量在 ieee 754 标准双精度中应等于 2 0 我正在使用的代码是 define two 0x4000000000
  • 汇编器8086将32位数字除以16位数字

    我尝试将 32 位数字除以 16 位数字 例如 10000000h 除以 2000h 根据我尝试做的设计除以 右 4 位数字除以除数 然后左 4 位数字除以除数 这是我的代码 DATA num dd 10000000h divisor dw
  • 学习 (N)ASM 的最佳资源是什么? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想学习汇编已经有一段时间了 尽管我之前尝试过几次 但我还没有真正能够超越 Hello world 有
  • 如何在 MacOS 上使用 nasm 进行编译

    我正在尝试在汇编器上编译并链接我的第一个程序 我尝试编译以下代码 include stud io inc global main section text main xor eax eax again PRINT Hello PUTCHAR
  • NASM:如何正确访问SSD驱动器?

    我需要使用 NASM 16 位代码访问 SSD 驱动器 访问普通硬盘时 需要设置寄存器AX DX CX来选择柱面 磁道 扇区 扇区数 AH 选择读扇区功能 DL 选择驱动器号 CH 选择气缸 DH 选择磁盘上的一侧 CL 选择步入正轨的部门
  • 在微控制器中将数据从内存移至内存

    为什么我们不能直接将数据从一个内存位置移动到另一个内存位置 如果我问了一个愚蠢的问题 请原谅我 但我认为这是真实的情况 至少对于我遇到的情况而言 8085 8086 n 80386 我并不是真正在寻找移动数据的解决方案 例如 使用 movs
  • 为什么此 NASM 代码会打印我的环境变量?

    本学期我刚刚完成计算机体系结构课程 除其他外 我们一直在涉足 MIPS 汇编并在 MARS 模拟器中运行它 今天 出于好奇 我开始在我的 Ubuntu 机器上摆弄 NASM 基本上只是将教程中的内容拼凑起来 并感受一下 NASM 与 MIP

随机推荐

  • 如何从 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