我目前正在编写一个汇编例程,但我听不懂。
我必须在文件.txt中写入例如字符串“ 000-00”,例程在此处(例程在堆栈中读取输出文件的指针并在其上写入字符串)(例程是从ac程序调用):
.data
.section .text
.global func
func:
pushl %ebp
movl %esp, %ebp
pushl %edi
pushl %esi
movl 12(%ebp), %edi
movl $VAL, (%edi)
movl $VAL2, 4(%edi)
popl %esi
popl %edi
popl %ebp
ret
该行中的
movl $VAL, (%edi)
VAL必须是允许我在字符串(%edi)上写字符串000-00的值。我该怎么办?将字符串转换为ASCII吗?我知道ASCII中的'0'是48,我想我必须为(48->'0'和45->'-')
写$ 48484845所以我认为字符串000-等于ASCII中的48484845。我究竟做错了什么?为什么要写:
movl $48, (%edi)
输出正确,并且在.txt文件中,我读取了charachter 0,我只是不理解如何在一条指令中编写多个ascii charachter。
谢谢,我的英语不好。
编辑:我发现了这个值:
movl $757935149, (%edi)
这条指令将写字符串“-,-”,我不怀疑,“-”的ASCII是45,而“,”是44 ...
答案 0 :(得分:2)
VAL必须是允许我在(%edi)字符串上写的值 000-00。我该怎么办?将字符串转换为ASCII吗?我知道 ASCII中的'0'是48,我以为我必须为(48->'0'写$ 48484845 和45->'-')
所以我认为字符串000-等于ASCII中的48484845。什么 我做错了吗?
您非常接近,但是您完全跳过了如何在计算机中对值进行编码的部分。 movl
将32位存储到内存中,并且内存可按字节(8位)进行寻址,通常以1字节= 1个ASCII字符的形式存储以ASCII编码的字符(即使纯ASCII只需要7位,因此第8位始终为零)。
因此,您需要的是值VAL
,该值将在内存中存储四个字节:48、48、48、45。
但是您的十进制值48484845有两个问题,一个是,当您检查二进制值的形式时,它是0000_0010_1110_0011_1101_0001_1110_1101
(或十六进制0x2E3D1ED
),而x86是little-endian系统,因此这32位将被拆分并以字节1110_1101
(237或0xED),1101_0001
(209或0xD1),1110_0011
(227或0xE3)和{{1 }}(2或0x02)。小尾数表示低8位首先进入内存(地址0000_0010
),高8位最后进入内存(地址edi+0
)。
因此,您需要将三个“ 48”值放入低24位,将值“ 45”放入前8位,即您需要将值edi+3
转换为十六进制时的值{{1} }。 48 + 48*256 + 48*256*256 + 45*256*256*256 = 758132784
会将值“向上”移动8位,因为2 8 = 256。
现在,如果您要注意那些十六进制值,您可能会注意到每个十六进制数字都是从正好4位构建的(而十进制0..9数字分布在与上一位/下一位数字共享的4位上,因此它们很难从二进制文件中进行组合/提取),并且使用0x2D303030
值实际上可以从头读取它,并将单独的字节视为2D_30_30_30,并且由于这些字节将以低位字节序存储在内存中,内存将设置为四个字节(十六进制):*256
,当以ASCII字符串读取时将形成0x2D303030
。因此,如果您需要在要设置特定位的位置定义一些常量,而又不想使用计算器或在源代码中进行写入(48 + 48 * 256),则通常可以通过以十六进制格式进行定义来避免这种情况,例如例如30 30 30 2D
设置16位值的最高位和最低位,并且每个两个六位数字正好形成一个字节(8位),因此您可以在十六进制格式中看到较大类型的单独字节值(例如word / dword / qword)(顺便说一句,0x8001是十进制的32769,这是我可以在头脑中计算出的值,因为自从8位计算机编程以来,我已经在内存中印上了两个的前16次幂,所以最高位是2 15 = 32768,最低位是2 0 = 1 ...,但是十六进制格式对于此类任务更加简单和方便。)
BTW "000-"
写入4个字节(0x8001
上的“ l”后缀表示“ long” = 32位值),因此您要写入四个字符:movl $48,(%edi)
。同样,这也是您的原始任务,如果您只输出“ 000-00”,而不输出其他任何内容,那么第二个mov
和48, 0, 0, 0
应该是mov
,以便仅将两个字节写入内存, VAL2
将值movw $0x3030, 4(%edi)
存储为四个字节movl
,即在字符串后添加两个零字节。
如果调用程序例程确实为字符串缓冲区保留了足够的空间(至少8个字节),并且仅将6个字节写入磁盘上的文件,则第二个0x3030
是无害的。如果调用方只有6个字节的缓冲区,则第二个48, 48, 0, 0
是缓冲区溢出错误。