Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用交换方法反转程序集中的外部阵列-x86 MASM_C++_Arrays_Assembly_Masm - Fatal编程技术网

C++ 使用交换方法反转程序集中的外部阵列-x86 MASM

C++ 使用交换方法反转程序集中的外部阵列-x86 MASM,c++,arrays,assembly,masm,C++,Arrays,Assembly,Masm,我正在做一个项目,我们需要将char类型的数组作为参数传递,并反转数组。我觉得我很快就要完成了,但是我被困在了实际的交换过程中 我在.Masm中使用了交换函数,我使用了C++中的相同方法(使用未登记的寄存器作为临时变量,然后交换前面和后面)。我不理解的是我将如何改变那个地址的实际内容。我假设执行以下操作将“更改”目标地址的内容: mov eax,[edx] 然而,这并没有按计划进行。在我运行for循环再次遍历数组之后,一切都保持不变 如果有人能给我指出正确的方向,那就太好了。我已经在下面的代码

我正在做一个项目,我们需要将char类型的数组作为参数传递,并反转数组。我觉得我很快就要完成了,但是我被困在了实际的交换过程中

<>我在.Masm中使用了交换函数,我使用了C++中的相同方法(使用未登记的寄存器作为临时变量,然后交换前面和后面)。我不理解的是我将如何改变那个地址的实际内容。我假设执行以下操作将“更改”目标地址的内容:

mov eax,[edx]
然而,这并没有按计划进行。在我运行for循环再次遍历数组之后,一切都保持不变

如果有人能给我指出正确的方向,那就太好了。我已经在下面的代码中提供了尽可能多的注释

而且,我在一个.asm文件中完成了所有这些工作;但是,我的教授希望我为以下每个函数提供3个单独的.asm文档:swap、reverse和getLength。我试图将另一个2.asm文档包含在reverse.asm中,但它一直给我一个错误

程序集代码开始:

.686
.model flat

.code

_reverse PROC 
    push ebp
    mov ebp,esp ;Have ebp point to esp

    mov ebx,[ebp+8] ;Point to beginning of array
    mov eax,ebx
    mov edx,1
    mov ecx,0
    mov edi,0
    jmp getLength

getLength:
    cmp ebp, 0          ;Counter to iterate until needed to stop
    je setup

    add ecx,1
    mov ebp,[ebx+edx]
    add edx,1
    jmp getLength

setup:                  ;This is to set up the numbers correctly and get array length divided by 2
    mov esi,ecx
    mov edx,0
    mov eax,ecx
    mov ecx,2
    div ecx

    mov ecx,eax
    add ecx,edx         ;Set up ecx(Length of string) correctly by adding modulo if odd length string
    mov eax,ebx
    dec esi

    jmp reverse

reverse:                ;I started the reverse function by using a counter to iterate through length / 2
    cmp edi, ecx
    je allDone

    mov ebx,eax         ;Set ebx to the beginning of array
    mov edx,eax         ;Set edx to the beginning of array
    add ebx,edi         ;Move ebx to correct index to perform swap
    add edx,esi         ;Move edx to the back at the correct index

    jmp swap            ;Invoke swap function

swap:
    mov ebp,ebx         ;Move value to temp
    mov ebx,[edx]       ;Swap the back end value to the front
    mov edx,[edx]       ;Move temp to back

    inc edi             ;Increment to move up one index to set up next swap
    dec esi             ;Decrement to move back one  index to set up for next swap

    jmp reverse         ;Jump back to reverse to setup next index swapping

allDone:
    pop ebp
    ret

_reverse ENDP

END
C++代码开始:

#include <iostream>
#include <string>

using namespace std;

extern "C" char reverse(char*);

int main()
{
    const int SIZE = 20;
    char str1[SIZE] = { NULL };

    cout << "Please enter a string: ";
    cin >> str1;

    cout << "Your string is: ";

    for (int i = 0; str1[i] != NULL; i++)
    {
        cout << str1[i];
    }

    cout << "." << endl;

    reverse(str1);

    cout << "Your string in reverse is: ";

    for (int i = 0; str1[i] != NULL; i++)
    {
        cout << str1[i];
    }

    cout << "." << endl;

system("PAUSE");
return 0;
}
#包括
#包括
使用名称空间std;
外部“C”字符反转(字符*);
int main()
{
常数int SIZE=20;
char str1[SIZE]={NULL};
cout>str1;

cout
mov-eax[edx]
(假设采用英特尔语法)将内存中地址edx处的32位放入eax。也就是说,此代码从内存位置检索数据。如果要写入mem位置,则需要将其反转,即
mov[edx],eax

在通宵使用一些16位代码进行排序后,我有以下两个可能有用的函数。显然,你不能复制/粘贴它们-你必须研究它们。但是,你会注意到它可以交换任意大小的项。非常适合交换某些类型结构的元素

; copies cx bytes from ds:si to es:di
copyBytes:
    shr     cx, 1
    jnc     .swapCopy1Loop
    movsb
.swapCopy1Loop:
    shr     cx, 1
    jnc     .swapCopy2Loop
    movsw
.swapCopy2Loop:
    rep     movsd
    ret

;               bp+0        bp+2   bp+4
;void swap(void *ptr1, void *ptr2, int dataSizeBytes)
swapElems:
    push    bp
    mov     bp, sp
    add     bp, 4
    push    di
    push    si
    push    es

    mov     ax, ds
    mov     es, ax

    sub     sp, [bp+4]      ; allocate dataSizeBytes on the stack, starting at bp-6 - dataSizeBytes

    mov     di, sp
    mov     si, [bp+0]
    mov     cx, [bp+4]
    call    copyBytes

    mov     si, [bp+2]
    mov     di, [bp+0]
    mov     cx, [bp+4]
    call    copyBytes

    mov     si, sp
    mov     di, [bp+2]
    mov     cx, [bp+4]
    call    copyBytes

    add     sp, [bp+4]

    pop     es
    pop     si
    pop     di
    pop     bp
    ret     2 * 3

因此,经过多个小时的修补和查找,我终于能够找到如何正确复制一个字节。如果有人需要,我将在下面发布我的.asm代码,并附上注释,以供将来参考

我实际上是将当前地址的内容移动到32位寄存器中。在我将其从mov ebx[eax]更改为mov bl[eax]后,它正确地复制了值

我将只张贴代码,我有困难,所以我不会把整个项目给其他学生

ASM代码如下:

swap:
mov bl,[edx]        ;Uses bl since we are trying to copy a 1 byte char value
mov bh,[eax]        ;Uses bh since we are trying to copy a 1 byte char value

mov [edx],bh        ;Passing the value to the end of the array
mov [eax],bl        ;Passing the value to the beginning of the array

inc eax             ;Moving the array one index forward
dec edx             ;Moving the array one index backwards

dec ecx             ;Decreasing the counter by one to continue loop as needed

jmp reverse         ;Jump back to reverse to check if additional swap is needed

感谢大家的帮助。

您使用的是英特尔汇编语法。在该语法中,第一个操作数是目标,第二个是源,但不是源。由于我对整个括号(即[edx])感到困惑,我认为[edx]中的任何内容都将取代ebx的内容(当前有第一个索引的地址)。例如在C++中(因为我更熟悉C++):int i=25;int *p=和i;*p=35;这是当我执行MOV EBX、[EDX]时发生的情况吗???在这种情况下,
edx
指向的32位内存将被复制到
ebx
。感谢您的回复!因为这基本上是我第一次使用汇编,所以我对一些语法不太熟悉。因为在课堂上他只教我们如何将ebp推入堆栈,我真的不明白为什么我们需要使用它将另一个寄存器放入堆栈中。我会在线查看更多信息,但如果答案很短,请您澄清一下好吗?谢谢!没关系。我只能看到您的代码只使用
push
一次,所以我假设您想知道为什么我将其他寄存器放入堆栈中。这样我们就可以恢复它们的原始版本nal值在我们完成使用后,可以使它们处于调用函数时的任何状态。例如,
copyBytes
-此函数不会推/弹出其任何寄存器,因此当它完成时,CX、SI和DI寄存器都发生了更改-我知道调用
copyBytes
的函数会这样做esn不依赖这些保持不变的寄存器,所以我没有费心保存它们。很抱歉延迟。我再次处理了它,并使它工作了一些。它能够将最后一个字母复制到阵列的前面,但其余的都是垃圾。我仔细研究了它,我相信我理解了这个问题。因为我正在执行mov eax,[ebx],它实际上是复制4个字节。我的目标是在该位置复制一个字节,因为它是一个字符。我如何在该位置处理1个字节?有趣的是,您只需使用一个较小的寄存器作为
tmp
变量。例如,
mov al,[edx]
对于1字节,
mov ax,[edx]
用于2个字节,而
mov eax,[edx]
用于4个字节。因此,如果您有两个字节大小的元素要交换,edx指向elem1,而ebx指向elem2,您可以这样做:
mov al,[edx]
mov ah,[ebx]
mov[edx],ah
mov[ebx],al
机会有多大!!事实上,我几分钟前才意识到这一点,并发布了一个答案。在我切换到较小的寄存器后,它立即起作用。感谢您在此过程中的帮助!我会将您的答案标记为答案,因为它也在注释中得到了回答。除非您确实缺少寄存器,否则您有时会看到per使用同一寄存器(bl和bh)的不同部分而不是两个不同寄存器(如al和dl)的性能惩罚。部分寄存器会在某些CPU上创建错误的依赖关系。如果可以,在不浪费mov指令的情况下,可以使用esi来保存源指针,使用edi来保存dest指针。这只是基于寄存器名称的标准约定,仅在您想使用
rep movs
或隐式使用esi和edi作为指针。另外,在