조립 : 두 가지 메모리 주소 사이에서 이동
-
18-09-2019 - |
문제
나는 어셈블리를 배우려고 노력하고 있습니다 (그래서 나와 함께 참아주세요).이 라인에서 컴파일 오류를 받고 있습니다.
mov byte [t_last], [t_cur]
오류는입니다
error: invalid combination of opcode and operands
이 오류의 원인은 단순히 MOV 명령이 두 메모리 주소 사이를 이동하는 것이 불가능하지만 반 시간의 인터넷 검색과 나는 이것을 확인할 수 없었다고 생각합니다. 이것이 사실입니까?
또한 내가 옳다고 가정하면 메모리 복사를위한 중간 지점으로 레지스터를 사용해야한다는 의미입니다.
mov cl, [t_cur]
mov [t_last], cl
권장되는 레지스터는 무엇입니까 (또는 스택을 대신 사용해야합니까)?
해결책
당신의 의심은 정확합니다. 기억에서 기억으로 이동할 수 없습니다.
모든 일반 목적 등록부는 할 것입니다. 내부에 무엇이 있는지 확실하지 않은 경우 레지스터를 푸시하고 한 번 다시 복원해야합니다.
다른 팁
16 비트로 정말 간단합니다. 다음을 수행하십시오.
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
참고 : 레지스터의 내용을 저장 해야하는 경우 푸시 및 팝은 반드시 필요합니다.
메모리에서 메모리로 데이터를 이동하는 것의 MOVS 명령도 있습니다.
MOV SI, OFFSET variable1
MOV DI, OFFSET variable2
MOVS
기술적으로 메모리에서 메모리로 이동하는 것이 가능합니다.
사용해보십시오 움직입니다 (문자열 이동) 및 설정 e] si 그리고 E] di, 바이트, 단어 등을 전송할 것인지에 따라
mov si, t_cur ; Load SI with address of 't_cur'
mov di, t_last ; Load DI with address of 't_last'
movsb ; Move byte from [SI] to [DI]
; Some dummy data
t_cur db 0x9a ; DB tells NASM that we want to declare a byte
t_last db 0x7f ; (See above)
임시 레지스터가 하나 인 일반로드 + 저장소를 사용하는 것보다 효율적이지 않지만 단일 명령으로 실제 사본을 수행합니다.
방법은 다음과 같습니다 움직입니다 사용해야하며 작동 방식 :https://www.felixcloutier.com/x86/movs:movsb:movsw:movsd:movsq
일반적으로 a와 함께 사용됩니다 rep
단일 요소가 아닌 블록 카피의 접두사. (현대 CPU는 상당히 효율적인 마이크로 코드를 가지고 있습니다 rep movsb
AVX 벡터로드/스토어 지침을 사용하여 루프 속도에 가깝습니다.)
맞습니다. x86 머신 코드는 두 가지로 명령을 인코딩 할 수 없습니다. 명백한 메모리 피연산자 (임의 주소가 지정된 주소 []
)
권장 레지스터는 무엇입니까?
저장/복원 할 필요가없는 레지스터.
모든 주류 32 비트 및 64 비트 전화 규칙에서 EAX, ECX 및 EDX는 콜 클로버링되므로 Al, CL 및 DL이 좋은 선택입니다. 바이트 또는 단어 사본의 경우 일반적으로 movzx
32 비트 레지스터, 8 비트 또는 16 비트 매장에로드하십시오. 이것은 레지스터의 이전 값에 대한 잘못된 의존성을 피합니다. 좁은 16 또는 8 비트 만 사용하십시오 mov
적극적으로로드하십시오 원하다 다른 값의 낮은 비트로 합쳐지기 위해. x86 movzx
팔과 같은 지침의 아날로그입니다 ldrb
.
movzx ecx, byte [rdi] ; load CL, zero-extending into RCX
mov [rdi+10], cl
64 비트 모드에서 SIL, DIL, R8B, R9B 등도 훌륭한 선택이지만 매장의 기계 코드에 Rex 접두사가 필요하므로 피해야 할 작은 코드 크기의 이유가 있습니다.
다음 링크를 읽고 이해하지 못하고 허위 종속성 또는 부분 등록 마구간을 읽지 않는 한 일반적으로 AH, BH, CH 또는 DH를 쓰지 마십시오. 코드에서 문제가되지 않거나 전혀 발생하지 않습니다. .
- GCC가 부분 레지스터를 사용하지 않는 이유는 무엇입니까?
- Haswell/Skylake의 부분 레지스터가 정확히 어떻게 수행됩니까? Al을 쓰는 것은 Rax에 대한 잘못된 의존성 인 것처럼 보이며 Ah는 일치하지 않습니다.
(또는 스택을 대신 사용해야합니까)?
우선, 단일 바이트를 전혀 밀 수 없으므로 스택에서 바이트 하중 / 바이트 상점을 수행 할 수있는 방법이 없습니다. 단어, dword 또는 qword (CPU 모드에 따라) push [src]
/ pop [dst]
, 그러나 레지스터를 통해 복사하는 것보다 훨씬 느립니다. 데이터를 최종 대상에서 읽기 전에 추가 상점/새로 고침 저장소 대기 시간을 소개하고 더 많은 UOP를 사용합니다.
스택 어딘가에 ~이다 원하는 목적지와 해당 로컬 변수를 레지스터로 최적화 할 수 없습니다. push [src]
거기에 복사하고 스택 공간을 할당하는 것이 좋습니다.
보다 https://agner.org/optimize/ 및 기타 X86 성능 링크 x86 태그 위키
"메모리 배리어"에 대해 논의하고 싶습니다. C 코드에서
a = b;//Take data from b and puts it in a
조립됩니다
mov %eax, b # suppose %eax is used as the temp
mov a, %eax
시스템은 과제의 원자력을 보장 할 수 없습니다. 그것이 우리가 RMB가 필요한 이유입니다 (읽기 장벽)