16. Пpоцедуpа получает пpи вызове начальный адpес массива из N*M целых чисел в pегистpах DS:DX и подсчитывает пpоизведение отpицательных элементов пеpвой стpоки таблицы.
Я долго думал и пытался её реализовать. Но всё выходило через.... как обычно кароче. Тогда я накодил в Паскале эту же прогу
var j,x:integer;
a:array [1..100,1..100] of integer;
begin
a[1,1]:=-4;
a[1,2]:=-2;
a[1,3]:=-5;
a[1,4]:=3;
a[2,1]:=1;
a[2,2]:=2;
a[2,3]:=3;
a[2,4]:=4;
x:=1;
for j:=1 to 4 do
if a[1,j]<0 then
x:=x*a[1,j];
writeln('x= ',x);
readln;
end.
и попытался IDA её дизассемблировать. Получился очень смутный и нерабочий код.
.code
start:
push ebp
mov ebp, esp
add esp, 0FFFFFFF0h
push esi
mov eax, off_40AA9C
mov byte ptr [eax], 1 ; точно не знаю, но вроде это команда x:=1;
mov eax, offset dword_408C54
call sub_405424
mov dword_40F908, 0FFFFFFFCh ; -4
mov dword_40F90C, 0FFFFFFFEh ; -2
mov dword_40F910, 0FFFFFFFBh ; - 5
mov dword_40F914, 3
mov dword_40FA98, 1
mov dword_40FA9C, 2
mov dword_40FAA0, 3
mov dword_40FAA4, 4
;for j:=1 to 4 do
mov esi, 1 ; делать от 1
mov edx, 4 ; до 4
;if a[1,j]<0 then
mov eax, offset dword_40F908 ; копируем в еах содержимое 40F908 (a[1,j])
telo_cikla:
test eax, eax ; проверяем равен ли eax нулю
jge short noshow ; если больше или равно нулю, то переходим на loc_4091B5( когда условие не выпонилось)
;x:=x*a[1,j]
imul esi, eax ; иначе умножаем esi на ecx
; этого в паскале не видно, но нужно, здесь мы уменьшаем счетчик цикла и (переменная j) и меняем элемент массива - ну типо вначале первый потом второй и тп
noshow:
add eax, 4 ; eax+4 (таким образом мы смотрим массив, по элементам)
dec edx ;edx -1 (щетчик цикла)
jnz short telo_cikla ;если еdx не равно нулю то переходим на loc_4091AC - продолжаем цикл
; иначе
;writeln('x= ',x);
; вызов writeln разлагается на два вызова writeln вначале вывадим x а затем наше значение
;writeln('x= ')
mov eax, off_40A9F0 ;какой-то параметр функции, думаю говорит о том что нужно выводить данные на новой строке
mov edx, offset dword_4091F8 ;символ x
call sub_404A24 ; вызов функции writeln
mov edx, esi ; непосредственно значение x, как видим без доп параметра, значет будем печатать не с новой строки, а продолжим на старой в
; результате x=40, 40 - это к примеру взял
;readln; тут незнаю замороченный вызов readln.
call sub_4036C4
call sub_4036F0
call sub_402DDC
mov eax, off_40AA5C
call sub_40340C
call sub_402DDC
pop esi
call sub_404518
end start
Вот и пробую создать рабочий вариант. Помогите кто сможет.