Assembly 汇编程序如何将常量作为数据放入文件中,以及如何以这种方式执行?

Assembly 汇编程序如何将常量作为数据放入文件中,以及如何以这种方式执行?,assembly,Assembly,例如,在Assembly x86中,我们可以使用.data entry部分静态定义如下所示的数据字节: MSG db 'CAGA', AAFF 我的问题涉及汇编程序如何或如何实现将数据插入到二进制文件中,假设我们正在汇编到一个平面二进制(bin)文件 我想知道,因为我正在尝试反编译,并更好地理解如何使用机器代码编程 看,我想用机器代码对系统软件进行编码,但汇编程序抽象掉了一些机器代码概念(如静态数据声明、对齐、指令宽度、语句结构、操作数或一般代码),我处于停顿状态 我只是想问,关于机器代码,它

例如,在Assembly x86中,我们可以使用.data entry部分静态定义如下所示的数据字节:

MSG db 'CAGA', AAFF
我的问题涉及汇编程序如何或如何实现将数据插入到二进制文件中,假设我们正在汇编到一个平面二进制(bin)文件

我想知道,因为我正在尝试反编译,并更好地理解如何使用机器代码编程

看,我想用机器代码对系统软件进行编码,但汇编程序抽象掉了一些机器代码概念(如静态数据声明、对齐、指令宽度、语句结构、操作数或一般代码),我处于停顿状态

我只是想问,关于机器代码,它是如何在这些基本原理中进行阐述的:

程序的.data部分是如何静态添加到文件中的?当CPU获取指令时,它如何在运行时/处理时使用?例如,在下面这个程序中,这是一个在FASM上使用英特尔语法汇编代码的x86引导加载程序

    [BITS 16]   ;Tells the assembler that its a 16 bit code
[ORG 0x7C00]    ;Origin, tell the assembler that where the code will
                ;be in memory after it is been loaded

MOV SI, HelloString ;Store string pointer to SI
CALL PrintString    ;Call print string procedure
JMP $       ;Infinite loop, hang it here.


PrintCharacter: ;Procedure to print character on screen
    ;Assume that ASCII value is in register AL
MOV AH, 0x0E    ;Tell BIOS that we need to print one charater on screen.
MOV BH, 0x00    ;Page no.
MOV BL, 0x07    ;Text attribute 0x07 is lightgrey font on black background

INT 0x10    ;Call video interrupt
RET     ;Return to calling procedure



PrintString:    ;Procedure to print string on screen
    ;Assume that string starting pointer is in register SI

next_character: ;Lable to fetch next character from string
MOV AL, [SI]    ;Get a byte from string and store in AL register
INC SI      ;Increment SI pointer
OR AL, AL   ;Check if value in AL is zero (end of string)
JZ exit_function ;If end then return
CALL PrintCharacter ;Else print the character which is in AL register
JMP next_character  ;Fetch next character from string
exit_function:  ;End label
RET     ;Return from procedure


;Data
HelloString db 'Hello World', 0 ;HelloWorld string ending with 0

TIMES 510 - ($ - $$) db 0   ;Fill the rest of sector with 0
DW 0xAA55           ;Add boot signature at the end of bootloader
HelloString db'Hello World',0”以0和1的形式静态插入到bin文件中,但在机器代码中,静态二进制数据如何通过存储到寄存器的字符串指针地址作为操作数添加到MOV SI指令中


基本上,如何将文件中的静态二进制数据字节作为代码操作数执行以移入源索引寄存器

MOV SI,HelloString

真的是

MOV SI,偏移量HelloString

实际的字符串HelloString被放置在二进制流中,就像代码作为字节序列一样。对于分段代码,它通常位于一个单独的数据段中,根据平台的不同,可以使用不同的名称。对于COM文件之类的东西,数据通常只跟随代码区域,通常从适当对齐的地址开始

更新:

我目前无法访问16位系统,但下面是32位x86代码中类似的内容:

Binary code    Instruction
BEA43F4600     mov esi, offset @HelloString  
E8F2FFFFFF     call PrintString
EBFE           @1: jmp @1
48656C6C6F     @HelloString: "Hello"

当然@HelloString的实际偏移量和PrintString的实际地址取决于上下文。

问题的答案取决于二进制文件的执行方式

假设目前使用Linux或MS windows等操作系统, 二进制文件很复杂,包含头信息等。让我们忽略这一点,然后 一旦程序在内存中,请集中精力查看它的外观

它稍微简单一点

代码区

代码序曲

MOV AL,BL

代码postlude

数据区

我的数据: 数据“caga”,0AH

该地区的传统称为路段。现在这个名字被英特尔劫持了,它们被微软和linux(ELF)称为Section。不过,两者之间有着密切的关系。 MOV是程序开始的地方,但需要一个设置前奏 还有一段时间(否则你再也回不到Linux了)。 在奔腾上的典型Linux/Windows环境中,您将看到Intel段硬件支持这些部分。底线是,您将无法跳转到MYDATA,即设置程序计数器以包含MYDATA。相反,在linux上,硬件会给你带来“分段错误”,在Windows上可能会出现蓝屏

可以肯定的是,您可以执行“数据”,因为实际上代码只是在正确的位置和时间执行的数据。例如,您可以通过在下面的行中输入
SECTION.text

(傻,我知道。这不是我编造的。)

在汇编程序代码部分,你可以说
MOV AL,BL
它将把0x88和0xD8放在两个连续字节的代码段中。 如果你将

DB 0x88,0xD8

在程序中的同一位置

您将了解到,上述内容已大大简化。例如,一个典型的ELF二进制文件很容易包含20个部分。它对英特尔来说也有点具体,但具体比抽象更容易理解

您的示例显然是一种引导情况。它不完整,因为HelloString丢失。现在,如果我们将其添加到程序的末尾,HelloString将作为一个地址被记住,即一个数字。组装MOV SI时,。。指示留下了一个洞来填那个数字。在对整个文件处理一次之后,HelloString地址就被知道了,汇编程序会将其填入


Groetjes Albert

我不太明白-你能在pics中或更深入地定义吗?从技术上讲,我只是想知道这在裸机上是如何工作的(即引导后,从单个文件执行指令;没有操作系统、内存管理、内核等)。为了简单起见,不过还是要谢谢你。请注意,文件只存在于操作系统中。我对我的答案进行了编辑,以便更具体地说明你的例子。