【问题标题】:Memory transfer intel assembly AT&T内存传输英特尔组件 AT&T
【发布时间】:2015-05-16 14:38:42
【问题描述】:

我在将字符串从一个内存地址按字节移动到另一个内存地址时遇到问题。在这里待了几个小时并尝试了一些不同的策略。我是 Intel 组件的新手,所以我需要一些技巧和见解来帮助我解决问题。

getText 例程应该将 n(在 %rsi 中)字节从 ibuf 传输到 %rdi 中的地址。 counterI 是用于指示从何处开始传输的偏移量,在例程结束后,它应该指向下一个未传输的字节。如果没有 n 个字节,它应该取消传输并在 %rax 中返回实际传输的字节数。

getText:
        movq    $ibuf, %r10
        #in rsi is the number of bytes to be transfered
        #rdi contains the memory adress for the memory space to transfer to
        movq    $0, %r8     #start with offset 0
        movq    $0, %rax    #zero return register
        movq    (counterI), %r11
        cmpb    $0, (%r10, %r11, 1) #check if ibuf+counterI=NULL
        jne MOVE            #if so call and read to ibuf
        call    inImage
    MOVE:       
        cmpq    $0,%rsi         #if number of bytes to read is 0
        je  EXIT            #exit
        movq    counterI, %r9       
        movq    $0, %r9         #used for debugging only shold not be 0
        movb  (%r10, %r9, 1), %bl   #loads one byte to rdi from ibuf
        movb  %bl, (%rdi, %r8, 1)
        incq    counterI        #increase pointer offset
        decq    %rsi            #dec number of bytes to read
        incq    %r8         #inc offset in write buffert
        movq    %r8, %rax       #returns number of bytes wrote to buf 
        movq    (counterI), %r9 
        cmpb    $0, (%r10, %r9,1)   #check if ibuf+offset is NULL
        je  EXIT            #if so exit
        cmpq    $0, %rsi        #can be cleaned up later
        jne MOVE
    EXIT:
        movb    $0, (%rdi, %r8, 1)  #move NULL to buf+%r8?          
        ret

【问题讨论】:

  • 这个函数的语义应该是什么? counterI 起什么作用? inImage 是什么?为什么要将读取的字节进行零扩展,然后写入整个 qword? (这将在末尾写入 7 个额外的零,通常不需要)此外,如果您要复制字符串,则不必在终止符之前停止 然后添加额外的终止符,您可以复制它并然后检测它是否是终止符。你也弹出了一些东西而没有推送一些东西/改变了 rsp,所以它会弹出返回地址,然后返回到遗忘状态。
  • getText 应该将最多 n 个字节传输到寄存器 %rdi 中的地址。 counterI 是 ibuf 中的当前偏移量。 inImage 是一个从标准输入写入字符串的函数,在本例中为 ibuf。问题是我尝试使用 movb 但当我尝试将其放入 %r# 寄存器时它会抱怨。我更改了推送 %r12 并没有注意到弹出:D 我更关注从一个内存地址移动到另一个正确的问题。

标签: memory assembly x86 intel


【解决方案1】:
movq    counterI, %r9       
movq    $0, %r9         #used for debugging only shold not be 0

第二条指令使第一条指令无用,但鉴于我理解您将删除它的评论。更好的是,如果您将每次出现的 %R9 都更改为 %R11,则可以将两者都删除。

movzbq  (%r10, %r9, 1), %r10    #loads one byte+zeroes to rdi from ibuf
movq    %r10, (%rdi, %r8, 1)    #HERE IS THE PROBLEM I THINK

这是一个危险的构造。您首先使用 %R10 作为地址,然后在其中删除一个零扩展数据字节。稍后在代码中您将再次使用 %R10 作为地址,但遗憾的是它不会在那里!解决方案是移入不同的寄存器,而不用担心零扩展。

movb  (%r10, %r9, 1), %bl   #loads one byte to rdi from ibuf
movb  %bl, (%rdi, %r8, 1)

以下代码可以缩短

 cmpb    $0, (%r10, %r9,1)   #check if ibuf+offset is NULL
 je  EXIT            #if so exit
 cmpq    $0, %rsi        #can be cleaned up later
 jne MOVE
EXIT:

作为

 cmpb    $0, (%r10, %r9, 1)   #check if ibuf+offset is NULL
 jne MOVE
EXIT:

【讨论】:

    猜你喜欢
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    • 2020-03-21
    • 1970-01-01
    • 2019-09-01
    • 1970-01-01
    相关资源
    最近更新 更多