汇编代码如何与机器码相对应呢?

时间:2021-09-12 12:17:01
汇编代码如何与机器码相对应呢?
今天我为了搞清这个问题,写了一个实验程序,如下
re1:
mov ax,1
re2:
mov ax,1
re3:
mov ax,1
re4:
mov ax,1
re5:
mov ax,1
jmp re1
jmp re2
jmp re3
jmp re4
jmp re5
用ultra edit打开,因无数据段,从200h开始的机器码为
B8,01,00  B8,01,00  B8,01,00  B8,01,00  B8,01,00

EB,EF  EB,F0  EB,F1  EB,F2  EB,F3 
那么, EB,EF~ ~ ~EB,F3中EB(JMP)后的数值代表什么呢?
是虚地址么?还是别的什么?
它与程序中指令的地址之间的对应关系是怎样的?就是说,
EB,EF是怎么跳到MOV,AX(第一个)的呢?

17 个解决方案

#1


將對應的標號轉化為地址偏移,這是編譯器作的事。

#2


to:SoRoMan(lkl) 
你的意思是EF,F0,F1之类的是地址偏移么?
不过我用debug看了一下,此程序的cs是0B52,
5个MOV AX,1的偏移为0,3,6,9,c,
不知你所说的偏移指的是这个么?

#3


这个工作由汇编程序来完成.

#4


那汇编程序是依据什么来完成的呢?
它是将偏移地址经过怎么样的变换变成EF,F0,F1之类的呢?

#5


这是设计CPU时就定下来的.因为计算机只认识二进制数, 所以机器指令最终也用二进制数.

#6


to:Purpleendurer(Purplenendurer) 

呵呵,这个我知道,你没有太明白我的意思.

我是想知道汇编程序怎么把有标号指令的位置变换成16进制数,使得在程序执行时可以准确无误的跳到指定的位置!

如果我想把一个可执行程序的功能给扩充,在原程序的代码段后接上一些代码,这些代码有时候又要跳到原来的程序的某些指令处,这要怎么做呢?

(不用反汇编再重新编译的办法,只是将扩充代码的机器码写在原程序的’mov ah,4ch int 21h‘前面)

当然这样做显得很傻~~~~~~~~~~_~

#7


你是不是想破解?

#8


to:wenhu93k(lotus) 

也不是说破解,只是想了解一下源代码被编译和可执行程序执行时到底是怎样的?

#9


刚才看了一篇文章,初看觉得很有用,看到后来就更有些迷茫了!

贴上来大家讨论一下!

原文内容:

EXE文件是一种多段的结构,属于DOS最成功和复杂的设计之一。 
要了解EXE文件,首先需要了EXE的文件头结构。 
(大家先去wenyue.yeah.net下载一份HELPSTAR吧。上面有许多有关的东西。) 
Exe file header format 
Offset size Description 
00 2 bytes .EXE Type Flag,4d5ah 
02 2 bytes Bytes in the last page(512 bytes/page) 
04 2 bytes pages of the .EXE file(Include exeheader) 
06 2 bytes ReAllocation number 
08 2 bytes Exeheader size(16 bytes*this value) 
0a 2 bytes MinAlloc 
0c 2 bytes MaxAlloc 
0e 2 bytes The init stack segment 
10 2 bytes The int stack pointer 
12 2 bytes Checksum 
14 2 bytes Code pointer 
16 2 bytes Code segment 
18 2 bytes The offset of reallocation table 
1a 2 bytes The overlay number make by link 
聪明的人应该一眼就能分辨出我们最感兴趣的部分了,偏移14和16,这两个东东简直太重要了。它们表示了程序的执行代码入口地址。

最上面的那个程序是这样的
00000000h: 4D 5A 1D 00 02 00 00 00 20 00 00 00 FF FF 00 00 ; MZ...... .....
00000010h: 00 00 09 13 00 00 00 00 1E 00 00 00 01 00 00 00 ; ................
它的14(Code pointer)和16(Code segment)竟然都是0   ???
但是用debug调试时cs却是0B52,ip是0000!
这是怎么的说?

#10


不能只考虑汇编时的地址计算吧
EXE文件在装入内存时操作系统也是会为程序定位的

#11


对DOS下的EXE程序, 汇编程序主要是生成相对于段首地址的地址(段内偏移地址或者叫相对地址)

在EXE文件运行时, 段首地址才确定下来, 程序要进行跳转时, 由CPU将段首地址乘16再加上段内偏移地址得到实际要跳转的物理地址.

#12


对不起, 应该是:

汇编程序和连接程序主要是生成相对于段首地址的地址(段内偏移地址或者叫相对地址)

#13


Purpleendurer(Purplenendurer)
谢谢你,你使我明白了为什么上面程序的偏移14(Code pointer)和16(Code segment)为什么都是0!
但是我还是想知道汇编程序和连接程序是如何生成相对于段首地址的地址(段内偏移地址或者叫相对地址)的!
偏移地址经过怎么样的变换变成EF,F0,F1的呢?或者EF,F0,F1本身就是相对于段首地址的偏移?不过不应该呀!mov ax,1(第一个)应该是0呀!
或许我有点过于钻牛角尖了?呵呵~~~~~~~~~~~~~~~~~

#14


to:Purpleendurer(Purplenendurer)

你先前说过的“这是设计CPU时就定下来的”(回答:那汇编程序是依据什么来完成的呢?
它是将偏移地址经过怎么样的变换变成EF,F0,F1之类的呢?)
这句话我有点不太明白!

#15


http://developer.intel.com/design/pentium4/manuals/24547112.pdf

下载intel的Comment The IA-32 Intel? Architecture Software Developer’s Manual, Volume 2: Instruction Set Reference看。

#16


编译器在扫描的过程中,每条指令的相对地址是确定的(可以用简单计数表示),此时汇编程序就会根据标号re1与指令jmp re1之间的相对地址将指令jmp re1翻译成EB EF(EF是偏移-11的补码表示,表示向前偏移11H,此处即指向标号re1处).在整个的翻译过程中指令,数据的地址通常都是相对地址,因为此时各个段都还没定位下来.在编译过程中,cs,ds,es这些段值都是未确定的,除非你指定了绝对地址(这种做法是危险的).在程序被加载执行时,cs,ds,es这些段值才确定下来.而此时EB EF同样会指向向前偏移11H的标号re1处,因为相对地址未变,尽管环境变了.

#17


有意思

#1


將對應的標號轉化為地址偏移,這是編譯器作的事。

#2


to:SoRoMan(lkl) 
你的意思是EF,F0,F1之类的是地址偏移么?
不过我用debug看了一下,此程序的cs是0B52,
5个MOV AX,1的偏移为0,3,6,9,c,
不知你所说的偏移指的是这个么?

#3


这个工作由汇编程序来完成.

#4


那汇编程序是依据什么来完成的呢?
它是将偏移地址经过怎么样的变换变成EF,F0,F1之类的呢?

#5


这是设计CPU时就定下来的.因为计算机只认识二进制数, 所以机器指令最终也用二进制数.

#6


to:Purpleendurer(Purplenendurer) 

呵呵,这个我知道,你没有太明白我的意思.

我是想知道汇编程序怎么把有标号指令的位置变换成16进制数,使得在程序执行时可以准确无误的跳到指定的位置!

如果我想把一个可执行程序的功能给扩充,在原程序的代码段后接上一些代码,这些代码有时候又要跳到原来的程序的某些指令处,这要怎么做呢?

(不用反汇编再重新编译的办法,只是将扩充代码的机器码写在原程序的’mov ah,4ch int 21h‘前面)

当然这样做显得很傻~~~~~~~~~~_~

#7


你是不是想破解?

#8


to:wenhu93k(lotus) 

也不是说破解,只是想了解一下源代码被编译和可执行程序执行时到底是怎样的?

#9


刚才看了一篇文章,初看觉得很有用,看到后来就更有些迷茫了!

贴上来大家讨论一下!

原文内容:

EXE文件是一种多段的结构,属于DOS最成功和复杂的设计之一。 
要了解EXE文件,首先需要了EXE的文件头结构。 
(大家先去wenyue.yeah.net下载一份HELPSTAR吧。上面有许多有关的东西。) 
Exe file header format 
Offset size Description 
00 2 bytes .EXE Type Flag,4d5ah 
02 2 bytes Bytes in the last page(512 bytes/page) 
04 2 bytes pages of the .EXE file(Include exeheader) 
06 2 bytes ReAllocation number 
08 2 bytes Exeheader size(16 bytes*this value) 
0a 2 bytes MinAlloc 
0c 2 bytes MaxAlloc 
0e 2 bytes The init stack segment 
10 2 bytes The int stack pointer 
12 2 bytes Checksum 
14 2 bytes Code pointer 
16 2 bytes Code segment 
18 2 bytes The offset of reallocation table 
1a 2 bytes The overlay number make by link 
聪明的人应该一眼就能分辨出我们最感兴趣的部分了,偏移14和16,这两个东东简直太重要了。它们表示了程序的执行代码入口地址。

最上面的那个程序是这样的
00000000h: 4D 5A 1D 00 02 00 00 00 20 00 00 00 FF FF 00 00 ; MZ...... .....
00000010h: 00 00 09 13 00 00 00 00 1E 00 00 00 01 00 00 00 ; ................
它的14(Code pointer)和16(Code segment)竟然都是0   ???
但是用debug调试时cs却是0B52,ip是0000!
这是怎么的说?

#10


不能只考虑汇编时的地址计算吧
EXE文件在装入内存时操作系统也是会为程序定位的

#11


对DOS下的EXE程序, 汇编程序主要是生成相对于段首地址的地址(段内偏移地址或者叫相对地址)

在EXE文件运行时, 段首地址才确定下来, 程序要进行跳转时, 由CPU将段首地址乘16再加上段内偏移地址得到实际要跳转的物理地址.

#12


对不起, 应该是:

汇编程序和连接程序主要是生成相对于段首地址的地址(段内偏移地址或者叫相对地址)

#13


Purpleendurer(Purplenendurer)
谢谢你,你使我明白了为什么上面程序的偏移14(Code pointer)和16(Code segment)为什么都是0!
但是我还是想知道汇编程序和连接程序是如何生成相对于段首地址的地址(段内偏移地址或者叫相对地址)的!
偏移地址经过怎么样的变换变成EF,F0,F1的呢?或者EF,F0,F1本身就是相对于段首地址的偏移?不过不应该呀!mov ax,1(第一个)应该是0呀!
或许我有点过于钻牛角尖了?呵呵~~~~~~~~~~~~~~~~~

#14


to:Purpleendurer(Purplenendurer)

你先前说过的“这是设计CPU时就定下来的”(回答:那汇编程序是依据什么来完成的呢?
它是将偏移地址经过怎么样的变换变成EF,F0,F1之类的呢?)
这句话我有点不太明白!

#15


http://developer.intel.com/design/pentium4/manuals/24547112.pdf

下载intel的Comment The IA-32 Intel? Architecture Software Developer’s Manual, Volume 2: Instruction Set Reference看。

#16


编译器在扫描的过程中,每条指令的相对地址是确定的(可以用简单计数表示),此时汇编程序就会根据标号re1与指令jmp re1之间的相对地址将指令jmp re1翻译成EB EF(EF是偏移-11的补码表示,表示向前偏移11H,此处即指向标号re1处).在整个的翻译过程中指令,数据的地址通常都是相对地址,因为此时各个段都还没定位下来.在编译过程中,cs,ds,es这些段值都是未确定的,除非你指定了绝对地址(这种做法是危险的).在程序被加载执行时,cs,ds,es这些段值才确定下来.而此时EB EF同样会指向向前偏移11H的标号re1处,因为相对地址未变,尽管环境变了.

#17


有意思