Prosta i pobieżna analiza instrukcji

grzebalec

Użytkownik
Dołączył
Sierpień 20, 2013
Posty
2
Witam. Do assemblera zaglądam raz na ruski rok, ale coś mnie natchnęło, żeby spróbować jako tako zrozumieć pewne rzeczy.
Mam taki kod
Kod:
10001340  /$ 8B4424 08      MOV EAX,DWORD PTR SS:[ESP+8]
10001344  |. 8B4C24 10      MOV ECX,DWORD PTR SS:[ESP+10]
10001348  |. 0BC8           OR ECX,EAX
1000134A  |. 8B4C24 0C      MOV ECX,DWORD PTR SS:[ESP+C]
1000134E  |. 75 09          JNZ SHORT ETS2Lib.10001359
10001350  |. 8B4424 04      MOV EAX,DWORD PTR SS:[ESP+4]
10001354  |. F7E1           MUL ECX	
10001356  |. C2 1000        RETN 10
10001359  |> 53             PUSH EBX
1000135A  |. F7E1           MUL ECX	
1000135C  |. 8BD8           MOV EBX,EAX
1000135E  |. 8B4424 08      MOV EAX,DWORD PTR SS:[ESP+8]
10001362  |. F76424 14      MUL DWORD PTR SS:[ESP+14]
10001366  |. 03D8           ADD EBX,EAX
10001368  |. 8B4424 08      MOV EAX,DWORD PTR SS:[ESP+8]
1000136C  |. F7E1           MUL ECX
1000136E  |. 03D3           ADD EDX,EBX
10001370  |. 5B             POP EBX
10001371  \. C2 1000        RETN 10

IDA wysmażyła z tego coś takiego:
Kod:
__int64 sub_10001340(__int64 a1, __int64 a2) {
	__int64 result;	//qax@2
	if (HIDWORD(a1) | HIDWORD(a2)) result = a1*a2;
	else result = (_DWORD)a2 * (_QWORD)(DWORD)a1;
	return result;

Kilka pytań:
1. Dobrze rozumiem, że obecność zmiennych lokalnych można rozpoznać po [EBP-xxx]? Nie widzę również ramki stosu, skąd w takim razie wzięło się __int64 result?
2. IDA stwierdziła, że funkcja przyjmuje dwa 8-bajtowe argumenty. Jeśli dobrze rozumiem to a1 = [ESP+4] i [ESP+8], a2 = [ESP+C] i [ESP+10]. Czym jest [ESP+14] w instrukcji MUL? OK, w międzyczasie jest push, więc esp się zmniejszył.
3. Prosiłbym o wyjaśnienie instrukcji RETN 10. (czyszczenie stosu z 16 bajtów?)
4. Jaki jest sens 3 instrukcji (OR ECX,EAX) skoro jej wynik jest nadpisywany w kolejnej instrukcji poprzez MOV? Ma ona związek z JNZ?

Z góry dziękuje za odpowiedzi i wyjaśnienia :)
 
Ostatnia edycja:

shoorick

Użytkownik
Dołączył
Lipiec 17, 2008
Posty
66
to wygląda na kolejne mnożenie 64-bitowych liczb w częściach przez 32-bitowy instrukcji. wynik wróca przez edx/eax parę.
funkcja nie ma ramki stosu: dla funkcji 386p+ nie jest obowiazkowym używanie ramki stosu, bo argumenty można dostać przez [esp+X],
chciaż w złożonych funkcjach używanie ramki jest wygodnim (nie pamiętam, ale mov [ebp+X]... może być nawet krótsza od mov [esp+X]...)
retn 10 - wyczyszenia argumentów ze stosu: dwe liczby 64-bitowy: 2x8=16 bajtów.

or ecx,eax + jnz: "optymizacja" żeby nie robić MUL 0,0 ;)
 
Ostatnia edycja:

grzebalec

Użytkownik
Dołączył
Sierpień 20, 2013
Posty
2
Dziękuje za odpowiedź, rozjaśniło mi to sytuację. Szczególnie ta "optymalizacja" ;)
Przy okazji mam kolejne pytanie. Instrukcja
Kod:
SHLD EAX,ECX,CL
przesuwa w lewo o CL miejsc bity rejestru EAX a w miejsce najstarszych wstawia CL najmłodszych bitów z rejestru ECX jednocześnie nie modyfikując go.

Czyli
Kod:
SHLD EAX,ECX,15
SHL ECX,15
jest równoważne z kodem C++
Kod:
__int64 zmienna = zmienna << 15;
Dobrze to rozumuje? :confused:

Czy można znaleźć jakieś dobre materiały/artykuły o operowaniu w assemblerze na zmiennych 64bitowych? Przyznam, że trochę to skomplikowane, żeby się zorientować co gdzie jest ;)
 

shoorick

Użytkownik
Dołączył
Lipiec 17, 2008
Posty
66
nigdy nie używałem tej instrukcji 8) również myślę używanie jej z ECX może dać dziwny wynik :)
do czytania najdokładniejsze są manualy od intela (czasem nawet zbyt dokładne): poszukaj ich pdf-y ;)
IA-32 Intel Architecture
Software Developer’s
Manual
Volume 2:
Instruction Set Reference
pisze:
SHLD—Double Precision Shift Left
Opcode Instruction Description
0F A4 SHLD r/m16, r16, imm8 Shift r/m16 to left imm8 places while shifting bits from r16
in from the right
0F A5 SHLD r/m16, r16, CL Shift r/m16 to left CL places while shifting bits from r16 in
from the right
0F A4 SHLD r/m32, r32, imm8 Shift r/m32 to left imm8 places while shifting bits from r32
in from the right
0F A5 SHLD r/m32, r32, CL Shift r/m32 to left CL places while shifting bits from r32 in
from the right
Description
Shifts the first operand (destination operand) to the left the number of bits specified by the third
operand (count operand). The second operand (source operand) provides bits to shift in from the
right (starting with bit 0 of the destination operand). The destination operand can be a register
or a memory location; the source operand is a register. The count operand is an unsigned integer
that can be an immediate byte or the contents of the CL register. Only bits 0 through 4 of the
count are used, which masks the count to a value between 0 and 31. If the count is greater than
the operand size, the result in the destination operand is undefined.
If the count is 1 or greater, the CF flag is filled with the last bit shifted out of the destination
operand. For a 1-bit shift, the OF flag is set if a sign change occurred; otherwise, it is cleared. If
the count operand is 0, the flags are not affected.
The SHLD instruction is useful for multi-precision shifts of 64 bits or more.
Operation
COUNT ← COUNT MOD 32;
SIZE ← OperandSize
IF COUNT = 0
THEN
no operation
ELSE
IF COUNT > SIZE
THEN (* Bad parameters *)
DEST is undefined;
CF, OF, SF, ZF, AF, PF are undefined;
ELSE (* Perform the shift *)
CF ← BIT[DEST, SIZE – COUNT];
(* Last bit shifted out on exit *)
FOR i ← SIZE – 1 DOWNTO COUNT
DO
Bit(DEST, i) ← Bit(DEST, i – COUNT);
OD;
FOR i ← COUNT – 1 DOWNTO 0
DO
BIT[DEST, i] ← BIT[SRC, i – COUNT + SIZE];
OD;
FI;
FI;
 
Ostatnia edycja:
Do góry Bottom