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

Reverse external array in assembly using swapping method - x86 MASM

本文关键字:程序集 程序 集中 阵列 外部 交换 方法 x86 MASM      更新时间:2023-10-16

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

对于.asm中的交换函数,我使用了与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;
}

因此,经过数小时的修补和环顾四周,我终于能够找到如何正确地复制一个字节。如果有人需要的话,我会在下面发布我的.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

感谢所有提供帮助的人。

mov eax,[edx](假设intel语法)将在地址edx的内存中找到的32位放入eax。即,此代码从内存位置检索数据。如果你想写入内存位置,你需要反向,即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