C 从内存地址辅助(程序集)复制字

C 从内存地址辅助(程序集)复制字,c,assembly,mips,lc3,C,Assembly,Mips,Lc3,我正在尝试从内存中复制一些单词,并使用汇编将其保存到另一个内存地址。 我正在尝试为它编写代码,但我不确定其中的一些部分。我将简要描述我想做什么 源地址、目标地址和要复制的字数是函数的输入参数。根据您的描述,它听起来像一个普通的memcpy,只是您指定了要复制的字数而不是字节数。不确定整个堆栈缓冲区的想法来自哪里(?) 类似这样的操作会将单词从源地址复制到目标地址: sll $a2,$a2,2 addu $a2,$a1,$a2 ; $a2 = address of first byte past

我正在尝试从内存中复制一些单词,并使用汇编将其保存到另一个内存地址。 我正在尝试为它编写代码,但我不确定其中的一些部分。我将简要描述我想做什么


源地址、目标地址和要复制的字数是函数的输入参数。

根据您的描述,它听起来像一个普通的memcpy,只是您指定了要复制的字数而不是字节数。不确定整个堆栈缓冲区的想法来自哪里(?)

类似这样的操作会将单词从源地址复制到目标地址:

sll $a2,$a2,2
addu $a2,$a1,$a2  ; $a2 = address of first byte past the dest buffer
Loop:
    lw $t0,0($a0)
    sw $t0,0($a1)
    addiu $a0,$a0,4
    addiu $a1,$a1,4
    bne $a1,$a2,Loop
    nop

编辑:如果源缓冲区和目标缓冲区未在字边界上对齐,则需要使用lb/sb来避免数据对齐异常。

编辑:在分支后添加NOP

想一想你会如何在C中,在一个低水平上做到这一点

unsigned int *src,*dst;
unsigned int len;
unsigned int temp;
...
//assume *src, and *dst and len are filled in by this point
top:
  temp=*src;
  *dst=temp;
  src++;
  dst++;
  len--;
  if(len) goto top;
你混合了太多的东西,专注于一个计划。首先,您说您在两个寄存器中有一个源地址和目标地址,为什么涉及堆栈?您不是在复制或使用堆栈,而是在使用这两个地址

乘以4得到字节数是正确的,但是如果你一次复制一个单词,你不需要计算字节数,只需要计算单词数。这是假设源地址和目标地址是对齐的,或者您不必对齐。(如果未对齐,则每次执行一个字节)

这在汇编中是什么样子的,你可以转换成mips,这是伪代码: rs是源寄存器$a0,rd是目标寄存器$a1,rx是长度寄存器$a2,rt是临时寄存器。现在,如果要从内存加载一个字,请使用load word(lw)指令;如果要加载一个字节,请执行lb(load byte)指令

现在如果你一次复制字节而不是单词,那么

shift_left rx,2
top:
branch_if_equal rx,0,done
nop
load_byte rt,(rs)
store_byte rt,(rd)
add rs,rs,1
add rd,rd,1
subtract rx,rx,1
branch top
nop
done:

谢谢,让我试着在MIPS中实现,如果它有效,我会接受你的答案。两个代码都给我内存地址的算术错误。我正在我的问题区域上传代码,请看一看,告诉我我是否做错了什么。现在,对于mips中的每个分支或跳转,请在分支执行后输入nop。在你手动调整代码之前,请输入nop。如果使用gnu汇编程序,您可能需要.set_reorder或类似的指令,否则汇编程序在汇编时会将分支与前面的指令交换,或者更糟的是,让它按照您告诉它的去做gnu汇编程序需要一个指令。我还不确定如何做=(我们昨天在课堂上学习了branch,但我不知道你想让我包括在内是什么意思。set_reorderNOP=No Operation。它什么都不做(技术上它实现为SLL$0,$0,0).MIPS使用延迟分支-这意味着分支后的指令在实际执行分支之前执行-因此,为了避免那里的指令可能会弄乱复制循环,我在那里放了一个NOP。嗨,这两个代码在内存地址上都给了我算术错误。我正在问题区域上载代码请看一看,告诉我我是否做错了什么。嗨,麦克xx,如果我使用lb和sb,加法运算是否如下:addiu$a0,$a0,1和addiu$a1,$a1,1Oh我尝试了sb和lb两种加法运算,但仍然给出相同的错误=(我很抱歉成为这样的麻烦,也很抱歉打扰你们。我感谢你们给我提供的所有帮助。对于你们得到的异常4,请参阅我对我的答案所做的编辑。@Michael检查我在你们答案下方的评论。请XX从哪个地址执行代码?另外,这将有助于了解导致异常的确切行。我是using PCSpim来运行代码。我所做的就是单击run按钮,然后出现一个小弹出窗口,询问我在其中输入0x00400000的起始地址,出现错误,因此我尝试不同的地址,甚至0x10000000及以上。当我这样做时,我得到的错误是异常6
shift_left rx,2
top:
branch_if_equal rx,0,done
nop
load_byte rt,(rs)
store_byte rt,(rd)
add rs,rs,1
add rd,rd,1
subtract rx,rx,1
branch top
nop
done: