关于汇编语言中的标号和变量

渡码 2013-04-08 10:19:58

%include "pm.inc" ; 常量, 宏, 以及一些说明

org 0100h
jmp LABEL_BEGIN

[SECTION .gdt]
; GDT
; 段基址, 段界限 , 属性
LABEL_GDT: Descriptor 0, 0, 0 ; 空描述符
LABEL_DESC_CODE32: Descriptor 0, SegCode32Len - 1, DA_C + DA_32 ; 非一致代码段, 32
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ; 显存首地址
; GDT 结束

GdtLen equ $ - LABEL_GDT ; GDT长度
GdtPtr dw GdtLen - 1 ; GDT界限
dd 0 ; GDT基地址

; GDT 选择子
SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
; END of [SECTION .gdt]

[SECTION .s16]
[BITS 16]
LABEL_BEGIN:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0100h

; 初始化 32 位代码段描述符
xor eax, eax
mov ax, cs
shl eax, 4
add eax, LABEL_SEG_CODE32
mov word [LABEL_DESC_CODE32 + 2], ax
shr eax, 16
mov byte [LABEL_DESC_CODE32 + 4], al
mov byte [LABEL_DESC_CODE32 + 7], ah



我的问题:
1.对于最后四行代码中的标号LABEL_DESC_CODE32表示内存首地址还是相对于基址的偏移量?
2.对于声明GdtPtr的时候貌似加不加冒号都无所谓
3.org使程序指针的偏移量置为0100h,那么段基址是多少?
...全文
538 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
渡码 2013-04-22
  • 打赏
  • 举报
回复
希望的到各位耐心地解答
渡码 2013-04-21
  • 打赏
  • 举报
回复
引用 7 楼 arthasmingjing 的回复:
引用 5 楼 RJGCSS 的回复:引用 4 楼 arthasmingjing 的回复: 你看的是Orange's一个操作系统的实现吧,我也在看 1.对于最后四行代码中的标号LABEL_DESC_CODE32表示内存首地址还是相对于基址的偏移量? => 首先这是初始化32位保护模式下的代码段,是选择子选择描述符后的段基址,对于实模式下是基址的偏移 2.对于声明……
非常感谢您耐心地回答,但我还是有个问题,程序加载到内存,是不是从高地址加到低地址(程序的开头在高地址结尾在低地址)? 如果程序中jmp LABEL 对于这条指令在机器码中是相对于基址的偏移量,那么这个基址是谁,cs ? ds? cs:ip? 希望的到您的解答
wanghb1989 2013-04-17
  • 打赏
  • 举报
回复
引用 7 楼 arthasmingjing 的回复:
引用 5 楼 RJGCSS 的回复:引用 4 楼 arthasmingjing 的回复: 你看的是Orange's一个操作系统的实现吧,我也在看 1.对于最后四行代码中的标号LABEL_DESC_CODE32表示内存首地址还是相对于基址的偏移量? => 首先这是初始化32位保护模式下的代码段,是选择子选择描述符后的段基址,对于实模式下是基址的偏移 2.对于声明……
我想问下,如果不申明这个org是不是就不行了?还有难道在连接程序中,不自动改变程序的地址吗?要是多个汇编程序怎么办?(PS:我对这个汇编了解不多)
arthasmingjing 2013-04-16
  • 打赏
  • 举报
回复
引用 5 楼 RJGCSS 的回复:
引用 4 楼 arthasmingjing 的回复: 你看的是Orange's一个操作系统的实现吧,我也在看 1.对于最后四行代码中的标号LABEL_DESC_CODE32表示内存首地址还是相对于基址的偏移量? => 首先这是初始化32位保护模式下的代码段,是选择子选择描述符后的段基址,对于实模式下是基址的偏移 2.对于声明GdtPtr的时候貌似加不加冒号都无所谓 => 这个在NAS……
org 0100h是跳过DOS文件头部的256个字节,使.com程序能够正常运行 要了解ORG 0100h,就必须先了解程序段前缀PSP(Program Segment Prefix) 程序段前缀是一个操作系统(DOS)概念。当输入一个外部命令或通过EXEC子功能(系统功能调用INT21h,子功能号为4Bh)加载一个程序时,COMMAND确定当前可用内存的最低端作为程序段的起点,也就是程序被加载到内存空间的起点。在程序所占用内存的前256(0100h)个字节中,DOS会为程序创建前缀(PSP)数据区。PSP结构与CP/M中的“控制区域”概念十分接近,这是因为DOS就是从CP/M演变而来的。 DOS利用PSP与被加载的程序进行通信。PSP中有程序的返回地址、程序文件名等信息。 1. 16位DOS中,内存的物理地址=段地址*16 + 偏移量,比如段地址0xC0h,偏移量0x50h,则最后的物理地址是0xC0h * 16 + 0x50h = 0xC50h 2. ORG用来告诉汇编器,程序加载到内存时的初始偏移量为0x100h,用于跳过PSP。 比如你有一个标号Test的偏移地址是0x0Bh,当编译器看见ORG 0x100h后,就会给这个偏移加上0x100h,编译完成的.com文件中,这个偏移就变成了0x10Bh。 如果你没有加ORG 0100h,则偏移仍然是0x0Bh,则访问该标号时,就跑到PSP里了,因为程序段的前0100h个字节,都是PSP的数据,而不是用户数据。 同理,你写ORG 0x200h,则该标号的偏移地址在编译的.com文件中,会变成0x20Bh。 3. DOS下的.com程序肯定被加载的CS段+0x100h处,因为段的前0100h(256字节)是留给PSP的。这是操作系统DOS的概念,跟ORG没有关系,所以你写ORG 0200h,也不会让程序加载到CS段的0200h处。 4. JMP、CALL等会改变IP指针的指令所涉及的偏移地址,在程序载入内存后,会自动加上0100h偏移,如你在代码中写JMP 0x0Bh,在程序载入内存后,会自动修正为JMP 0x10Bh。而其他指令不会做自动修正,如你写MOV AX, 0x000Bh,程序载入内存后,仍然是MOV AX, 0x000Bh。 5. ORG指定偏移是一个编译期概念,编译产生的汇编程序就已经加上了0100h的偏移。而JMP等指令的偏移是在操作系统加载com文件到内存时调整的。
渡码 2013-04-15
  • 打赏
  • 举报
回复
这里段地址是多少? 相对于基址的偏移,这个基址是cs? 这段程序数据和代码是一个段?
渡码 2013-04-10
  • 打赏
  • 举报
回复
引用 4 楼 arthasmingjing 的回复:
你看的是Orange's一个操作系统的实现吧,我也在看 1.对于最后四行代码中的标号LABEL_DESC_CODE32表示内存首地址还是相对于基址的偏移量? => 首先这是初始化32位保护模式下的代码段,是选择子选择描述符后的段基址,对于实模式下是基址的偏移 2.对于声明GdtPtr的时候貌似加不加冒号都无所谓 => 这个在NASM中文手册里有。解释如下 N……
使程序在0100h开始编译执行 你这里的0100h才十六位,物理地址应该是20位
Hony杨 2013-04-10
  • 打赏
  • 举报
回复
1.既然是相对于当前段的偏移,该标号是不是不能超出该段的64kb的空间? => 实模式下是这样的。 2.变量名是不是代表起始地址? => 变量名的地址就是偏移地址。
arthasmingjing 2013-04-10
  • 打赏
  • 举报
回复
你看的是Orange's一个操作系统的实现吧,我也在看 1.对于最后四行代码中的标号LABEL_DESC_CODE32表示内存首地址还是相对于基址的偏移量? => 首先这是初始化32位保护模式下的代码段,是选择子选择描述符后的段基址,对于实模式下是基址的偏移 2.对于声明GdtPtr的时候貌似加不加冒号都无所谓 => 这个在NASM中文手册里有。解释如下 NASM对于一行中的空格符并没有严格的限制:labels可以在它们的前面有空格,或 其他任何东西。label后面的冒号同样也是可选的。(注意到,这意味着如果你想 要写一行'lodsb',但却错误地写成了'lodab',这仍将是有效的一行,但这一行不做 任何事情,只是定义了一个label。运行NASM时带上命令行选项'-w+orphan-labels' 会让NASM在你定义了一个不以冒号结尾的label时警告你。 3.org使程序指针的偏移量置为0100h,那么段基址是多少? => org不作用于PC指针,它会告诉汇编器将org下面产生的机器码按照.text文本段开始位置进行偏移;段基址不变 这个回答感觉有点模糊,我理解的是由于此程序是要在DOS下以.com文件执行,而.com有256字节的DOS头部,所以需要跳过这个头部,使程序在0100h开始编译执行
Hony杨 2013-04-09
  • 打赏
  • 举报
回复
1.对于最后四行代码中的标号LABEL_DESC_CODE32表示内存首地址还是相对于基址的偏移量? => 基址的偏移 2.对于声明GdtPtr的时候貌似加不加冒号都无所谓 => 这个属于汇编语言编写问题 3.org使程序指针的偏移量置为0100h,那么段基址是多少? => org不作用于PC指针,它会告诉汇编器将org下面产生的机器码按照.text文本段开始位置进行偏移;段基址不变
渡码 2013-04-09
  • 打赏
  • 举报
回复
引用 1 楼 HuiyuYang_fish 的回复:
1.对于最后四行代码中的标号LABEL_DESC_CODE32表示内存首地址还是相对于基址的偏移量? => 基址的偏移 2.对于声明GdtPtr的时候貌似加不加冒号都无所谓 => 这个属于汇编语言编写问题 3.org使程序指针的偏移量置为0100h,那么段基址是多少? => org不作用于PC指针,它会告诉汇编器将org下面产生的机器码按照.text文本段开始位置进行偏移;段基址不变
1.既然是相对于当前段的偏移,该标号是不是不能超出该段的64kb的空间? 2.变量名是不是代表起始地址?

4,437

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧