2009-08-19 12 views
16

Próbuję nauczyć assermbly (więc nosić ze mną) i dostaję błąd kompilacji na tej linii:Montaż: przemieszczanych między dwoma pamięci rozwiązuje

mov byte [t_last], [t_cur] 

błąd jest

error: invalid combination of opcode and operands 

Podejrzewam, że przyczyną tego błędu jest po prostu to, że nie jest możliwe, aby instrukcja mov poruszała się między dwoma adresami pamięci, ale pół godziny googlowania, a ja nie byłem w stanie tego potwierdzić - czy tak jest w tym przypadku?

Ponadto, zakładając, że mam rację to oznacza, że ​​trzeba użyć rejestru jako punkt pośredni do kopiowania pamięci:

mov cl, [t_cur] 
mov [t_last], cl 

Jaka jest zalecana do korzystania z rejestru (lub powinien używać zamiast stosu)?

+3

czasami lepiej iść do * źródła * zamiast googlowania, tutaj na przykład są instrukcje Intel 64 i IA-32 AM, gdzie można zobaczyć kombinacje operandów dla 'mov' , http://www.intel.com/Assets/PDF/manual/253666.pdf –

+0

Istnieją wyjątki od zasady, że instrukcja nie może przyjąć dwóch argumentów pamięci; zobacz [tutaj] (http://stackoverflow.com/questions/14510280/why-cant-mov-have-business-operands-as-memory-locations?lq=1#comment20229305_14510280). – legends2k

Odpowiedz

21

Twoje podejrzenie jest prawidłowe, nie możesz przejść z pamięci do pamięci.

Każdy rejestr ogólnego przeznaczenia zrobi. Pamiętaj, aby PUSH zarejestrować, jeśli nie jesteś pewien, co jest w środku i przywrócić go z powrotem, gdy zostanie to zrobione.

+0

Czy jest jakaś korzyść z używania rejestru poprzez przesuwanie danych na stos? – Justin

+2

Naciśnięcie i puknięcie ze stosu powoduje dodanie dwóch dodatkowych pamięci. – hirschhornsalz

3

Istnieje również komenda MOV od przenoszenia danych z pamięci do pamięci:

MOV SI, OFFSET variable1 
MOV DI, OFFSET variable2 
MOVS 
+0

Działa, ale wymaga dodatkowej opieki: musisz zapisać rejestry si i di. Domyślam się, że nie warto za kopiowanie jednego bajtu. – sharptooth

+5

Komendy łańcuchowe na x86 można uznać za przestarzałe. Nigdy ich nie używaj. Nigdy nie są szybsze niż kopiowanie "ręcznie", ale w większości przypadków są znacznie wolniejsze. – hirschhornsalz

+0

@hirschhornsalz, przepraszam Nekromantę, ale czy masz jakieś szczegółowe informacje o tym, że polecenia ciągów są w zasadzie przestarzałe? –

4

To naprawdę proste w 16 bitów, po prostu wykonaj następujące czynności:

 push  di 
    push  si 
    push  cx 
    mov  cx,(number of bytes to move) 
    lea  di,(destination address) 
    lea  si,(source address) 
    rep  movsb 
    pop  cx 
    pop  si 
    pop  di 

Uwaga: popycha & pops są konieczne, jeśli zachodzi potrzeba zapisania zawartości rejestrów.

+0

+1, ponieważ w pewnych okolicznościach dobrze jest znać wszystkie narzędzia w zestawie narzędzi.rep movsb/movsw są 1-bajtowymi opkodami, IIRC –

+0

W zależności od architektury, możesz użyć pusha zamiast popychać wszystkie rejestry pojedynczo i popa zamiast popping je wszystkie. – BalinKingOfMoria

+0

Działa to również w wersjach 32 i 64, z wyjątkiem tego, że używa rejestrów dla tego systemu bitowego. – Rahly

-2

Chcę tylko omówić "barierę pamięci" z tobą. W kodzie c

a = b; 

są montowane do

mov %eax, a # suppose %eax is used as the temp 
mov b, %eax 

system nie może zagwarantować niepodzielność przeniesienia. Dlatego potrzebujemy rmb (bariera odczytu)

+0

x86 nie może atomicznie kopiować danych z pamięci do pamięci. Bariery nie powodują atomowości, przerywają tylko zmianę kolejności (czas kompilacji lub czas działania lub oba, w zależności od bariery). –