用于写入ASCII字符串的汇编指令

问题描述 投票:0回答:1

我目前正在编写程序例程,我不明白。

我必须在文件.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,我认为我必须为$ 48484845写(48 - >'0'和45 - >' - ')

所以我认为字符串000-等于ASCII中的48484845。我究竟做错了什么?如果我写的话:

movl $48, (%edi) 

输出是正确的,在文件.txt中我读了字符0,我根本不知道如何在一条指令中写多个ascii字符串。

谢谢我的答案和我不好的英语。

编辑:我发现了这个值:

movl $757935149, (%edi)

并且此指令将写入字符串“ - , - ”我不明白,“ - ”的ASCII为45,“,”为44 ...

assembly inline-assembly
1个回答
2
投票

VAL必须是允许我在(%edi)上写入字符串000-00的值。我该怎么办?用ASCII转换字符串?我知道ASCII中的'0'是48,我认为我必须为$ 48484845写(48 - >'0'和45 - >' - ')

所以我认为字符串000-等于ASCII中的48484845。我究竟做错了什么?

你非常接近,但是你完全跳过了如何在计算机中编码值的部分。 movl将32位存储到内存中,内存可通过字节(8位)进行寻址,以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)和0000_0010(2或0x02)。小端意味着低8位首先进入存储器(地址为edi+0),最高8位进入存储器最后(地址为edi+3)。

因此,您需要将三个“48”值放入低24位并将值“45”放入前8位,即您需要值48 + 48*256 + 48*256*256 + 45*256*256*256 = 758132784,当您将其转换为十六进制时,0x2D303030*256将“移动”该值8位,因为28 = 256。

现在,如果您要注意那些六进制值,您可能会注意到每个十六进制数字都是从4位构建的(而十进制0..9位数分布在4位上,与前一位/下一位数部分共享,因此它们并不容易从二进制编写/提取),并且使用0x2D303030值实际上可以在头部读取它并将单独的字节看作2D_30_30_30,并且因为它们将以小端顺序存储到存储器中,所以内存将被设置为4 bytes(以hexa为单位):30 30 30 2D,当读取为ASCII字符串时将形成"000-"。因此,如果你需要在你想要设置特定位的地方定义一些常量,并且你不想使用计算器或写入源(48 + 48 * 256),你通常可以通过以十六进制格式定义它,如例如0x8001设置16位值的顶部和底部位,并且每两个六位数字恰好形成一个字节(8位),因此您可以在hexa格式中看到较大类型的单独字节值(如word / dword / qword) (顺便说一下,0x8001是十进制的32769,这是我可以在脑中计算的东西,因为自从8位计算机编程以来,我有两个印记在内存中的前16个幂,所以最高位是215 = 32768,底部位是20 = 1 ...但十六进制格式对于这类任务来说更简单方便。

BTW movl $48,(%edi)写入4个字节(mov上的“l”后缀表示“long”= 32位值),所以你要写四个字符:48, 0, 0, 0。也是你的原始任务,如果你应该输出真的只有“000-00”而没有别的,那么第二个movVAL2应该是movw $0x3030, 4(%edi)只写两个字节到内存,用movl你将值0x3030存储为四个字节48, 48, 0, 0,即在字符串后添加两个归零字节。

然后,如果调用程序例程确实为字符串缓冲区保留了足够的空间(至少8个字节),并且它只向磁盘上的文件写入6个字节,则第二个movl是无害的。如果调用者只有6个字节的缓冲区,那么第二个movl就是缓冲区溢出错误。

© www.soinside.com 2019 - 2024. All rights reserved.