'게임핵'에 해당되는 글 3건
- 2020.04.10 :: [AssemBly] 기본적인 명령어 모음
- 2020.04.10 :: [AssemBly] 기초 명령어 소개
- 2020.04.10 :: [치트엔진강의] 다중 포인터 추적 첫번째 방법 (7)
기본적인 어셈블리 명령어
명 령 어 |
설 명 |
|
Data Transfer |
||
MOV |
Move |
데이터 이동 (전송) |
PUSH |
Push |
오퍼랜드의 내용을 스택에 쌓는다 |
POP |
Pop |
스택으로부터 값을 뽑아낸다. |
XCHG |
Exchange Register/memory with Register |
첫 번째 오퍼랜드와 두 번째 오퍼랜드 교환 |
IN |
Input from AL/AX to Fixed port |
오퍼랜드로 지시된 포트로부터 AX에 데이터 입력 |
OUT |
Output from AL/AX to Fixed port |
오퍼랜드가 지시한 포트로 AX의 데이터 출력 |
XLAT |
Translate byte to AL |
BX:AL이 지시한 데이블의 내용을 AL로 로드 |
LEA |
Load Effective Address to Register |
메모리의 오프셋값을 레지스터로 로드 |
LDS |
Load Pointer to DS |
REG←(MEM), DS←(MEM+2) |
LES |
Load Pointer ti ES |
REG←(MEM), ES←(MEM+2) |
LAHF |
Load AH with Flags |
플래그의 내용을 AH의 특정 비트로 로드 |
SAHF |
Store AH into Flags |
AH의 특정 비트가 플래그 레지스터로 전송 |
PUSHF |
Push Flags |
플래그 레지스터의 내용을 스택에 쌓음 |
POPF |
Pop Flags |
스택으로부터 플래그 레지스터로 뽑음 |
Arithmetic |
||
ADD |
Add |
캐리를 포함하지 않은 덧셈 |
SBB |
Subtract with Borrow |
캐리를 포함한 뺄셈 |
DEC |
Decrement |
오퍼랜드 내용을 1 감소 |
NEG |
Change Sign |
오퍼랜드의 2의 보수, 즉 부호 반전 |
CMP |
Compare |
두 개의 오퍼랜드를 비교한다 |
ADC |
Add with Carry |
캐리를 포함한 덧셈 |
INC |
Increment |
오퍼랜드 내용을 1 증가 |
AAA |
ASCII adjust for Add |
덧셈 결과 AL값을 UNPACK 10진수로 보정 |
DAA |
Decimal adjust for Add |
덧셈 결과의 AL값을 PACK 10진수로 보정 |
SUB |
Subtract |
캐리를 포함하지 않은 뺄셈 |
AAS |
ASCII adjust for Subtract |
뺄셈 결과 AL값을 UNPACK 10진수로 보정 |
DAS |
Decimal adjust for Subtract |
뺄셈 결과의 AL값을 PACK 10진수로 보정 |
MUL |
Multiply (Unsigned) |
AX와 오퍼랜드를 곱셈하여 결과를 AX 또는 DX:AX에 저장 |
IMUL |
Integer Multiply (Signed) |
부호화된 곱셈 |
AAM |
ASCII adjust for Multiply |
곱셈 결과 AX값을 UNPACK 10진수로 보정 |
DIV |
Divide (Unsigned) |
AX 또는 DX:AX 내용을 오퍼랜드로 나눔. 몫은 AL, AX 나머지는 AH, DX로 저장 |
IDIV |
Integer Divide (Signed) |
부호화된 나눗셈 |
AAD |
ASCII adjust for Divide |
나눗셈 결과 AX값을 UNPACK 10진수로 보정 |
CBW |
Convert byte to word |
AL의 바이트 데이터를 부호 비트를 포함하여 AX 워드로 확장 |
CWD |
Convert word to double word |
AX의 워드 데이터를 부호를 포함하여 DX:AX의 더블 워드로 변환 |
Logic |
||
NOT |
Invert |
오퍼랜드의 1의 보수, 즉 비트 반전 |
SHL/SAL |
Shift logical / arithmetic Left |
왼쪽으로 오퍼랜드만큼 자리 이동 (최하위 비트는 0) |
SHR |
Shift logical Right |
오른쪽으로 오퍼랜드만큼 자리 이동 (최상위 비트 0) |
SAR |
Shift arithmetic Right |
오른쪽 자리이동, 최상위 비트는 유지 |
ROL |
Rotate Left |
왼쪽으로 오퍼랜드만큼 회전 이동 |
ROR |
Rotate Right |
오른쪽으로 오퍼랜드만큼 회전 이동 |
RCL |
Rotate through Carry Left |
캐리를 포함하여 왼쪽으로 오퍼랜드만큼 회전 이동 |
RCR |
Rotate through Carry Right |
캐리를 포함하여 오른쪽으로 오퍼랜드만큼 회전 이동 |
AND |
And |
논리 AND |
TEST |
And function to Flags, no result |
첫 번째 오퍼랜드와 두 번째 오퍼랜드를 AND하여 그 결과로 플래그 세트 |
OR |
Or |
논리 OR |
XOR |
Exclusive Or |
배타 논리 합 (OR) |
String Manipulation |
||
REP |
Repeat |
REP 뒤에 오는 스트링 명령을 CX가 0이 될 때까지 반복 |
MOVS |
Move String |
DS:SI가 지시한 메모리 데이터를 ES:DI가지시한 메모리로 전송 |
CMPS |
Compare String |
DS:SI와 ES:DI의 내용을 비교하고 결과에 따라 플래그 설정 |
SCAS |
Scan String |
AL 또는 AX와 ES:DI가 지시한 메모리 내용 비교하고 결과에 따라 플래그 설정 |
LODS |
Load String |
SI 내용을 AL 또는 AX로 로드 |
STOS |
Store String |
AL 또는 AX를 ES:DI가 지시하는 메모리에 저장 |
Control Transfer |
||
CALL |
Call |
프로시저 호출 |
JMP |
Unconditional Jump |
무조건 분기 |
RET |
Return from CALL |
CALL로 스택에 PUSH된 주소로 복귀 |
JE/JZ |
Jump on Equal / Zero |
결과가 0이면 분기 |
JL/JNGE |
Jump on Less / not Greater or Equal |
결과가 작으면 분기 (부호화된 수) |
JB/JNAE |
Jump on Below / not Above or Equal |
결과가 작으면 분기 (부호화 안 된 수) |
JBE/JNA |
Jump on Below or Equal / not Above |
결과가 작거나 같으면 분기 (부호화 안 된 수) |
JP/JPE |
Jump on Parity / Parity Even |
패리티 플레그가 1이면 분기 |
JO |
Jump on Overflow |
오버플로가 발생하면 분기 |
JS |
Jump on Sign |
부호 플레그가 1이면 분기 |
JNE/JNZ |
Jump on not Equal / not Zero |
결과가 0이 아니면 분기 |
JNL/JGE |
Jump on not Less / Greater or Equal |
결과가 크거나 같으면 분기 (부호화된 수) |
JNLE/JG |
Jump on not Less or Equal / Greater |
결과가 크면 분기 (부호화된 수) |
JNB/JAE |
Jump on not Below / Above or Equal |
결과가 크거나 같으면 분기 (부호화 안 된 수) |
JNBE/JA |
Jump on not Below or Equal / Above |
결과가 크면 분기 (부호화 안 된 수) |
JNP/JPO |
Jump on not Parity / Parity odd |
패리티 플레그가 0이면 분기 |
JNO |
Jump on not Overflow |
오버플로우가 아닌 경우 분기 |
JNS |
Jump on not Sign |
부호 플레그가 0이면 분기 |
LOOP |
Loop CX times |
CX를 1감소하면서 0이 될 때까지 지정된 라벨로 분기 |
LOOPZ/LOOPE |
Loop while Zero / Equal |
제로 플레그가 1이고 CX≠0이면 지정된 라벨로 분기 |
LOOPNZ/LOOPNE |
Loop while not Zero / not Equal |
제로 플레그가 0이고 CX≠0이면 지정된 라벨로 분기 |
JCXZ |
Jump on CX Zero |
CX가 0이면 분기 |
INT |
Interrupt |
인터럽트 실행 |
INTO |
Interrupt on Overflow |
오버플로우가 발생하면 인터럽트 실행 |
IRET |
Interrupt Return |
인터럽트 복귀 (리턴) |
Processor Control |
||
CLC |
Clear Carry |
캐리 플레그 클리어 |
CMC |
Complement Carry |
캐리 플레그를 반전 |
CLD |
Clear Direction |
디렉션 플레그를 클리어 |
CLI |
Clear Interrupt |
인터럽트 플레그를 클리어 |
HLT |
Halt |
정지 |
LOCK |
Bus Lock prefix |
|
STC |
Set Carry |
캐리 플레그 셋 |
NOP |
No operation |
|
STD |
Set Direction |
디렉션 플레그 셋 |
STI |
Set Interrupt |
인터럽트 인에이블 플레그 셋 |
WAIT |
Wait |
프로세서를 일지 정지 상태로 한다 |
ESC |
Escape to External device |
이스케이프 명령 |
2. 8086 어셈블러 지시어(Directive)
지시어 |
내 용 |
형 식 |
SEGMENT - END |
어셈블리 프로그램은 한 개 이상의 세그먼트들로 구성된다. SEGMENT 지시어는 하나의 세그먼트를 정의한다. |
segname SEGMENT ; 세그먼트 시작 ⋮ ; 세그먼트 내용 segname ENDS ; 세그먼트 끝 |
PROC - ENDP |
매크로 어셈블리에서는 프로그램의 실행 부분을 모듈로 작성할 수 있다. 이 모듈을 프로시저(Procedure)라 부르며, PROC 지시어가 이를 정의한다. |
procname PROC ; 프로시저의 시작 ⋮ ; 프로시저의 내용 procname ENDP ; 프로시저의 끝 |
ASSUME |
어셈블러에게 세그먼트 레지스터와 사용자가 작성한 세그먼트의 이름을 연결시킨다. |
ASSUME SS:stack_segname, DS:data_segname, CS:code_segname, ES:extra_segname |
END |
전제 프로그램의 끝을 나타냄 |
END |
데이터 정의 지시어 : 프로그램에서 데이터를 저장할 기억 장소를 정의, 초기값 부여 |
||
DB |
Define Byte |
name DB 초기값 |
DW |
Define Word |
name DW 초기값 |
DD |
Define Double Word |
name DD 초기값 |
DQ |
Define Quad Word |
name DQ 초기값 |
DT |
Define Ten Bytes |
name DT 초기값 |
EQU |
변수 이름에 데이터값이나 문자열 정의 |
name EQU 데이터값/문자열 |
= |
EQU와 달리 정의된 값을 변경 가능 |
|
EVEN |
어셈블리시 이 지시어가 사용되는 곳의 주소가 짝수로 되도록 함 |
|
PAGE |
어셈블리 리스트의 형식을 결정 |
PAGE [length][,width] |
TITLE |
어셈블리 리스트의 각 페이지에 제목 출력 |
TITLE text |
※ 세그먼트(SEGMENT)와 오프셋(OFFSET)
16비트 레지스터를 사용하여 주소를 표현한다면, 216Byte = 65536 Byte = 64 KByte 의 주소 공간을 가질 수 있다. 그러나 지정 가능 주소 공간의 크기를 늘리기 위하여
'세그먼트', '오프셋'의 개념을 사용한다. 개념적으로는 메모리를 가리키는 화살표를
세그먼트(SEGMENT)라고 하고 그곳을 기준으로 떨어진 변위(DISPLACEMENT)를
오프셋(OFFSET)이라고 한다.
8086은 세그먼트를 16바이트 단위로 취하여 그곳으로부터 오프셋 지정으로 주소값을 얻는다.
세그먼트값 × 16 + 오프셋 = 실제주소
16을 곱한다는 것은 왼쪽으로 4번 시프트 한것과 같다. 이 때, 세그먼트 레지스터는
16비트이므로 실제 주소는 16비트를 왼쪽으로 4번 시프트한 20비트의 주소 공간을
가리킬 수 있게된다.
예를 들어, 세그먼트가 A000, 오프셋이 00FF 일 때 실제 주소 값은 다음과 같이 계산할 수 있다.
|
A |
0 |
0 |
0 |
|
세그먼트 |
+ |
|
0 |
0 |
F |
F |
오프셋 |
|
A |
0 |
0 |
F |
F |
실제 주소값 |
이러한 세그먼트, 오프셋에 의한 방식의 장점은 작은 레지스터 크기로도
넓은 주소 공간을 가리킬 수 있다는 것이다.
8086의 경우 20비트의 주소 공간이므로 220Byte = 1048576 Byte = 1 MByte 까지의 주소 공간을 가질 수 있다.
'AssemBly' 카테고리의 다른 글
[AssemBly] 메모리 기초강의 (0) | 2020.04.10 |
---|---|
[AssemBly] 기초 명령어 소개 (0) | 2020.04.10 |
Assembly 명령어 소개!
mov,lea 는 데이터이동
add, sub, inc, dec 는 논리,연산
cmp, jmp 는 흐름제어
call, rat 은 프로시저
push, pop 는 스텍조작
mov = 데이터 이동할때 사용함
lea = 주소값을 옮길려고 할때 사용함
add = 레디스터나 메모리의 값을 더하기 할때
sub = 레지스터나 메모리의 값을 뺄셈할때
dec = 값을 1 감소 시킬때
inc = 값을 1 증가 시킬때
cmp = 레지스터와 레지스터의 값을 서로 비교할때
jmp = 특정한 곳으로 분기 시킬때
call = 프로시저를 호출하고싶을때
ret = 호출했던 바로 다음 지점으로 이동시킬때
push = 값을 스택에 저장하고싶을때
pop = 값을 스텍에 삭제하고 싶을때
'AssemBly' 카테고리의 다른 글
[AssemBly] 메모리 기초강의 (0) | 2020.04.10 |
---|---|
[AssemBly] 기본적인 명령어 모음 (0) | 2020.04.10 |
다중 포인터 추적해보자
튜토리얼에 나온 값을 스캔합시다.
치트테이블의 값을 오론쪽 클릭 Findout what accesses this address 클릭합시다.
그러면 새창이 뜹니다. 값에 변화가 있을때 누가 이 주소에 접근했는지 추적해주는 창입니다.
튜토리얼에서 Change value를 클릭해줍니다.
Change value를 클릭할때마다 값이 변하죠?
그러면 값을 쓰기/읽기 위해 접근하는 것들을 모두 감지해 목록에 표시해줍니다.
참고로 진행중에 Change pointer를 클릭해버리면 포인터위치가 다 변해버립니다.
실수로라도 클릭하지 않도록 주의하세요.
2개가 나왔네요 여기서는 하나는 쓰기 하나는 읽기입니다.
mov eax,[esi+18]이 읽기입니다.
이유 > Findout what writes this address로 볼때 mov[esi+18,eax가 나와서 입니다.
그러니 mov eax,[esi+18]을 더블클릭합니다.
TIP - Findout what accesses this address = 쓰기 + 읽기 탐지
Findout what writes this addresswrites = 쓰기만 탐지
포인터의 상세한 정보가 나타납니다.
하지만 저희가 봐야할곳은 [OOOOOO]입니다.
esi > 001FFA78 이네요~ 그리고 오프셋은 18이네요!
값이 나왔네요
여기서는 메모장을 활용하세요.
첫번째
주소
[0027FBF0]
오프셋
[18]
방금 치트테이블에 등록한것을 오른클릭 - Find out what accesses this address 클릭합시다
튜토리얼에서 Change value 클릭하세요
mov eax,[esi]더블클릭하고 esi와 offset을 적어둔후 닫아주시면됩니다.
esi > 0027FBF0 / 오프셋은 0이네요
값 > 0027FBF0 를 스캔 > 주소 02FCE01C 를얻었습니다.
이거 또한메모합시다.
첫번째
주소
[0027FBF0]
오프셋
[18]
두번째
주소
02FCE01C
오프셋
0
방금 등록한 값을 오론쪽으로 클릭합시다.
튜토리얼에서 Change value를 클릭합시다
esi > [02FCE008] 오프셋 > [14] 이네요
띠~용 값이 두개나 나왔네요 당황하지말고 둘다 해보시면 됩니다!
튜토리얼에서Change value를 클릭했을때 하나는 아무것도 안뜨고 다른하나는 하던대로 뜹니다.
찾았다! 이 가짜놈 버립시다.
여기에서 또 메모 하셔야합니다 ^^
순서
1
주소
[0027FBF0]
오프셋
[18]
순서
2
주소
02FCE01C
오프셋
0
순서
3
주소
0029DFCC
오프셋
14
esi > 0029DFC0 오프셋은 0C
오우 드디어 찾았습니다. 원하고 원하던 초록색 값...
순서
1
주소
[0027FBF0]
오프셋
[18]
순서
2
주소
[02FCE01C]
오프셋
[0]
순서
3
주소
[0029DFCC]
오프셋
[14]
순서
4
주소
[0057C3A0]
오프셋
[0C]
어드레스 메모리뷰어 클릭합시다.
포인터 클릭한후 코드값/오프셋 메모한거 적으시면 됩니다!
처음에 있던값이랑 현재에 있던값이랑 동일하다면 성공한거입니다.
벨류 [5000] 으로 변경한후 OK 클릭!
짜짠~ 넥스트버튼이 활성화가 됐네요!