[英]Reverse external array in assembly using swapping method - x86 MASM
我正在一個項目中,我們需要將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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.