Assembly 创建For循环以填充程序集中充满破折号的空缓冲区

Assembly 创建For循环以填充程序集中充满破折号的空缓冲区,assembly,x86,att,Assembly,X86,Att,这就是我到目前为止得到的,每次我到代码的循环部分,我都会得到分段错误(内核转储)。这是因为我的一些寄存器保存的东西大小不正确吗 .data Welcome: .ascii "Welcome to League of Legends!!.\n\0" Instruction: .ascii "Player 1, enter a Champion's name: \0" Text: .space 12 Text2: .

这就是我到目前为止得到的,每次我到代码的循环部分,我都会得到
分段错误(内核转储)
。这是因为我的一些寄存器保存的东西大小不正确吗

 .data
   Welcome:
        .ascii "Welcome to League of Legends!!.\n\0"
  Instruction:
        .ascii "Player 1, enter a Champion's name: \0"
  Text:
        .space 12
  Text2:
        .space 12

  Guess:
        .ascii "Guess a letter: \0"
  Letter:
        .space 1
  SecretCharacter:
        .ascii "Your Champion is: \0"

  .text

  .global _start

  _start:
         mov $Welcome, %rax
        call PrintCString

        mov $Instruction, %rax
        call PrintCString
        mov $Text, %rax
        mov $12, %rbx
        call ScanCString
        mov %rax, %rbx
        mov %rax, %rbp
        call LengthCString
        mov %rax, %rcx


        mov $0, %rdi
        mov $45, %ch

Loop:
        cmp %rcx, %rdi
        jge End

        mov $Text2, %eax
        movb %ch, (%rax, %rdi)
        add $1, %rdi
        jmp Loop

End:
        call PrintCString
        call EndProgram

您同时使用rcx和ch,但ch是rcx的一部分。尝试使用dh而不是ch。

mov$Text2,%eax
应该是
mov$Text2,%rax
。此外,它应该在循环上方而不是内部。@prl:是的,它应该在循环外部,但在Linux上,静态地址保证在低32位的地址空间中,因此使用5字节零扩展的
mov r32、imm32
而不是7字节的
mov r/m64、符号扩展的-imm32
可以节省代码大小。(GAS不会为您进行优化,即使是像
$1
这样的数值常量,更不用说链接时间常量了)。对于独立于位置的可执行文件(或者即使不需要PIC,静态地址也不适合32位的OS X),您可以使用
leatext2(%rip),%rax
。那么,在这种情况下,
mov$Welcome,%rax
和其他一些错误。我知道是这样或那样的。@prl:好吧,反正效率很低。但是,对于一个不关心效率的初学者来说,这和mov$0、%rdi并不是“错误的”,尽管如此。@Bobbin:或者更好,
%dl
避免了。通常,加载完整寄存器后,仅使用AH/BH/CH/DH获取较大值的字节。(例如,
mov(%rdi),%eax
movzbl%al,%ecx
movzbl%ah,%edx
shr$16,%eax
;…)@PeterCordes当您始终分别使用低部分和高部分时,使用ah、bh、ch和dh不是很好吗?@fuz:在至少分别重命名高部分寄存器的CPU上,是的。(在AMD和Silvermont/KNL上,书写
ah
/
al
都在rax上有一个错误的dep(因此彼此都有)。在HSW/SKL上,可能会消耗额外的物理寄存器文件条目。我认为虽然它很脏,但重复阅读它并没有延迟惩罚。但是如果中断处理程序保存/恢复它,中断处理程序将遭受合并uop的惩罚,合并uop必须在一个周期内自行发出,然后在合并后读取DH会有额外的1c延迟。很小,但严格来说比DL@PeterCordes正如图所示,低寄存器并不是严格地优于高寄存器:因为它们是单独重命名的,所以在重写时可以避免持续的错误依赖(例如,
mov
ah
可以以4/周期运行,但是
mov
al
每个周期仅运行1个,因为它错误地依赖于
eax
的高位),虽然这在这里并不重要。@BeeOnRope:是的,使用
mov-ah,r/m8
,但不使用
mov-ah,imm8
setcc-ah
。但是如果您正在编写可移植的性能代码,您必须为Ryzen或任何在RAX上编写ah时总是有一个错误的dep的地方做好准备。所以是的,低8个reg并不总是更好或相等l比high8高,但一般来说,我绝对建议不要写入high8寄存器,除非你有理由。