2016-06-14 2 views
-2

Я должен поменять регистровые переменные eax, ebx, не создавая новый регистр. Это запрещено с помощью XCHG, CMPXCHG и их вариантов. Я пробовал это, но это не сработало. В чем проблема в моем коде. Является ли замена XOR правильным методом?XOR swap Assembly NASM

%include "asm_io.inc" 

SECTION .data 

x: dd 10 
y: dd 50 

fmt2: db "Value of myInteger X is %d",10,0 
fmt1: db "Value of myInteger Y is %d",10,0 


SECTION .text 

extern printf 
global asm_main 

asm_main: 

    push ebp 
    mov ebp, esp 



    mov eax, DWORD x 
    mov ebx, DWORD y 

    xor eax, ebx 
    xor ebx, eax 
    xor eax, ebx 

    push DWORD [x] 
    push fmt2 
    call printf 

    push DWORD [y] 
    push fmt1 
    call printf 


    mov esp, ebp 
    pop ebp 
    ret 
+1

Он работает, но вы меняете только регистры, а не 'x' и' y', которые вы печатаете, вы можете использовать вместо этого push-eax и 'push ebx'. PS: в следующий раз правильно использовать форматирование кода. PS # 2: 'ebx' является регистром с сохранением вызывающего абонента. – Jester

+0

спасибо jester. Я не понимаю, как заменить x и y. не могли бы вы мне помочь, пожалуйста? – Sedem

+1

Если вы хотите поменять местами x и y в памяти, проще всего записать их с заменой: 'mov eax, [x]; mov edx, [y]; mov [x], edx; mov [y], eax'. Обратите внимание, что 'xor' не работает с 2 операндами памяти. – Jester

ответ

2

Ваш xor swap действителен и работает хорошо. Это отпечаток результата, который неисправный (отображение исходных [x] и [y] значения, игнорируя местами результаты в eax ebx и выбросить

Либо добавить:.

mov [x],eax 
    mov [y],ebx 

сразу после 3х xor блока (сохранение результата обмена)

Или переписать отображение результатов использовать EAX/EBX, как, например:.

... 

    xor eax, ebx 
    xor ebx, eax 
    xor eax, ebx 

    ; prepare stack for printf ebx (new y) 
    push ebx 
    push offset fmt1 
    ; prepare stack for printf eax (new x) 
    push eax 
    push offset fmt2 
    ; do printf eax (new x) 
    call printf 
    ; do printf ebx (new y) 
    pop eax 
    pop eax  ; parameters of "printf eax" removed from stack 
    ; here stack points to the previously prepared ebx+fmt1 
    call printf 

BTW, я бы не использовал синтаксис mov eax, DWORD x, так как разные ассемблеры могут относиться к нему по-разному. Сначала вы можете оставить DWORD, так как это очевидно для ассемблера из использования регистра eax, а затем начните использовать [x] для ссылки на значение по адресу x или offset x для самого адреса. Поэтому в вашем коде я бы написал mov eax,[x], так как вы хотите загрузить eax со значением по адресу x. Таким образом, ваш стиль будет соответствовать таким вещам, как mov eax,[esi] vs mov eax,esi.

И вместо fmt1 и fmt2 вы должны использовать более осмысленное имя, как fmtx и fmty (держать его супер короткие, хотя с течением времени я научился не использовать слишком короткие символы, как и тогда я с трудом могу вспомнить, что это было через несколько дней).

Смежные вопросы