Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2017.08.27;
Скачать: [xml.tar.bz2];

Вниз

Передача параметров функции   Найти похожие ветки 

 
SergP ©   (2016-05-30 14:38) [0]

Допустим у меня есть такая функция с тремя параметрами:
function Search(count:integer; keyword:int64; var source):integer;

первый параметр, как я понимаю передается через EAX
Результат тоже вроде через EAX передается.
Третий похоже через EDX
А что со вторым?
Я не силен в ассемблере, но судя по коду он передается через стек. Если да, то где именно в стеке он находится?
насколько я понял, то на вершине стека находится адрес возврата (4 байта), а следом за ним параметр, ближе к вершине более младшие его байты. Правильно?

Т.е. такая функция будет работать?
(поиск в массиве по полю field. Если надено - возвращается номер элемента массива, если не найдено, то возвращается -1)

...
type TWork=packed record
  field:int64;
  MSet:TMset;
  Probe:Extended;
  end;
...
workarr:packed array of TWork;
...
function Search(count:integer; keyword:int64; var source):integer;
label
 lbloop, lbcont,lbbreak;
const
 step=sizeof(TWork);
asm
       push edx;
       push ecx;
       push ebx;
       mov  ecx,[esp+$10];
       mov  ebx,[esp+$14];
       dec  eax;
lbloop: cmp  ebx,[edx+$04];
       jnz  lbcont;
       cmp  ecx,[edx];
       jz   lbbreak;
lbcont: add  edx,step;
       dec  eax;
       jns  lbloop;
lbbreak:pop  ebx;
       pop  ecx;
       pop  edx;
end;


 
SergP ©   (2016-05-30 14:50) [1]

Глянул скомпилированный код.
Оно там вначале добавило:
push ebp;    // Зачем делать то, что я не просил?
mov ebp,esp;
push ebx;

и в конце:

mov eax,ebx; //Зачем оно мне result портит?
pop ebx;
pop ebp;
ret $0008; //что за параметр?
lea eax,[eax+$00]; //а это вообще что за чудо? или это просто мусор связанный с выравниванием?


 
SergP ©   (2016-05-30 14:53) [2]


> ret $0008; //что за параметр?


хотя что это такое вроде понял, если я правильно понял, то это число на которое дополнительно увеличивается ESP после возврата, из-за того что в стеке передавался параметр...
А вот как насчет всего остального?


 
Rouse_ ©   (2016-05-30 15:14) [3]

Вот так напиши:

function Search2(count:integer; keyword:int64; var source):integer;
const
step = sizeof(TWork);
asm
 push eax
 mov  ecx, eax
 mov  edx, [edx]
@compare:
 mov eax, [esp + 12]
 cmp [edx], eax
 jne @next
 mov eax, [esp + 16]
 cmp [edx + 4], eax
 je @done
@next:
 add edx, step
 dec ecx
 jnz @compare
 mov ecx, [esp]
 inc ecx
@done:
 pop eax
 sub eax, ecx
end;


 
SergP ©   (2016-05-30 15:23) [4]


>   mov eax, [esp + 12]
>   cmp [edx], eax
>   jne @next
>   mov eax, [esp + 16]
>   cmp [edx + 4], eax
>   je @done


Ну так сам компилятор делает подобным образом...
Я хотел сделать побыстрее... Т.е. хранить в регистрах второй параметр, чтобы постоянно его из памяти не дергать.

lbloop: cmp  eax,[edx+$04];
       jnz  lbcont;
       cmp  ecx,[edx];
       jz   lbbreak;


Вроде так заработало...:

function Search(count:integer; keyword:int64; var source):integer;
label
 lbloop, lbcont,lbbreak;
const
 step=sizeof(TWork);
asm
       push edx;
       push ecx;
       mov  ebx,eax;
       mov  ecx,[ebp+$08];
       mov  eax,[ebp+$0C];
       dec  ebx;
lbloop: cmp  eax,[edx+$04];
       jnz  lbcont;
       cmp  ecx,[edx];
       jz   lbbreak;
lbcont: add  edx,step;
       dec  ebx;
       jns  lbloop;
lbbreak:pop  ecx;
       pop  edx;
end;


Хотя какие-то странности пока имеются... Но возможно они связаны с другими участками кода.


 
SergP ©   (2016-05-30 15:25) [5]


> Хотя какие-то странности пока имеются... Но возможно они
> связаны с другими участками кода.


А. ну да. понял. я же по массиву вверх иду, а счетчик вниз считает... :)))


 
Rouse_ ©   (2016-05-30 15:28) [6]

в регистрах? ну тогда вот так:

function Search2(count:integer; keyword:int64; var source):integer;
const
step = sizeof(TWork);
asm
 push eax
 push esi
 mov  esi, [esp + 16]
 push edi
 mov  edi, [esp + 24]
 mov  ecx, eax
 mov  edx, [edx]
@compare:
 cmp  [edx], esi
 jne  @next
 cmp  [edx + 4], edi
 je   @done
@next:
 add  edx, step
 dec  ecx
 jnz  @compare
 mov  ecx, [esp + 8]
 inc  ecx
@done:
 pop  edi
 pop  esi
 pop  eax
 sub  eax, ecx
end;


 
Rouse_ ©   (2016-05-30 15:30) [7]

ну и пример вызова:

var
 workarr: packed array of TWork;
begin
 try
   SetLength(workarr, 10);
   workarr[0].field := 456;
   workarr[7].field := $CDB81F21CDB81F20;
   Writeln(Search2(10, $CDB81F21CDB81F20, workarr)); // result must be 7


 
SergP ©   (2016-05-30 16:13) [8]


>   dec  ecx
>   jnz  @compare


и еще вопрос: Вроде для таких вещей можно использовать команду loop, если бы она работала с 32-разрядным регистром.

Но вот по информации в инете не могу понять: какой все-таки регистр использует команда loop :  CX или ECX?

например как понять вот это:

> Команда LOOP уменьшает регистр-счетчик без изменения какого-
> либо из флагов. Затем проверяются условия характерные для
> конкретной формы используемой команды LOOP. Если условия
> удовлетворяются, то происходит короткий переход на метку,
>  заданную операндом команды LOOP.
>
> Если атрибут размера адреса равен 16 бит, то в качестве
> счетчика используется регистр CX, иначе — ECX.


Что подразумевается под атрибутом размера адреса?


 
Rouse_ ©   (2016-05-30 16:21) [9]


> и еще вопрос: Вроде для таких вещей можно использовать команду
> loop, если бы она работала с 32-разрядным регистром.

как правило не используют, она по тактам немного проигрывает.


> Что подразумевается под атрибутом размера адреса?

Префикс, указывающий с каким размером адресного регистра мы работаем.

Вот так цикл будет идти 65538 раз
 mov ecx, 65538
@loop:
 loop @loop


А вот так только два раза (т.к. в регистр CX будет равен двойке):

 mov ecx, 65538
@loop:
 db $67 // Address-size override prefix
 loop @loop


 
SergP ©   (2016-05-30 17:08) [10]

Чем отличаются команды JE от JZ и JNE от JNZ?


 
SergP ©   (2016-05-30 17:19) [11]


> add  edx, step


и еще: будет ли LEA edx,[edx+step] в данном случае быстрее?


 
Rouse_ ©   (2016-05-30 17:21) [12]

Ничем, ну только разве что читабельностью.
Для булевых операций обычно примеряют E (после test/cmp), для математических (add/sub/inc/dec) Z. В данном случае вычитается единица, и ожидаем результатом ноль, поэтому JNZ (опкоды у этих инструкций идентичные)


 
Rouse_ ©   (2016-05-30 17:22) [13]


> и еще: будет ли LEA edx,[edx+step] в данном случае быстрее?

нет, идентичны по тактам будут.


 
SergP ©   (2016-05-31 14:59) [14]

Почему в случае сабжевого кода (пусть он даже и не совсем верный), компилятор добавлял:

В начале:
push ebp;    
mov ebp,esp;
push ebx;

и в конце:
mov eax,ebx;
pop ebx;
pop ebp;
ret $0008;


А в случае [6], только

В начале
push ebp;    
mov ebp,esp;


и в конце:


pop ebp;
ret $0008;


т.е. чем вызвана эта самодеятельность компилятора:
...
push ebx;
...
mov eax,ebx;
pop ebx;
...

?
и как в будущем предугадать такие козни компилятора?


 
dmk ©   (2016-05-31 15:39) [15]

>т.е. чем вызвана эта самодеятельность компилятора:
Отладкой. Для Debug Kernel нужно. Точки останова и т.п.


 
dmk ©   (2016-05-31 15:40) [16]

Можно внешний obj подтянуть без использования ebp, но там точки останова не будут работать.


 
SergP ©   (2016-05-31 16:00) [17]


> dmk ©   (31.05.16 15:40) [16]
>
> Можно внешний obj подтянуть без использования ebp, но там
> точки останова не будут работать.


я не про ebp (то что компилятор всегда вставляет - то не страшно), а про то, что он вставляет непонятно когда... Иногда вставляет, а иногда нет.
Вот это:

...
push ebx;
...
mov eax,ebx;
pop ebx;
...


 
dmk ©   (2016-05-31 16:31) [18]

Сложно сказать. У меня Delphi XE6 и такого нет. Только BP, EBP, RBP.
Не нравится — вставляй по старинке obj"екты. Компилируй masm или еще чем.
Тогда точно будет так как написано.
Во времена Trubo Pascal и Delphi 3 я так и делал. Вставлял OBJ.

Кстати проверить еще можно отключив debug.
Run without Debugging Shitf+ Ctrl + F9.


 
Rouse_ ©   (2016-05-31 16:57) [19]


> Почему в случае сабжевого кода (пусть он даже и не совсем
> верный), компилятор добавлял:
>

Потому что, по пунктам:

1.
В начале
push ebp;    
mov ebp,esp;

и в конце:

pop ebp;
ret $0008;


Это стековый фрейм, он добавляется автоматом при использовании процедурой самого стека (под локальные переменные, под входные параметры).

2.
ret $0008
чистится стек из-за соглашения FASTCALL (в частности нивелируется передача второго параметра через стек)

3.
push ebx;
и в конце:
mov eax,ebx;
pop ebx;

EBX обьектный регистр, который нужно сохранять, видя что ты его используешь, компилер тебя подстраховывает


 
dmk ©   (2016-05-31 17:01) [20]

>видя что ты его используешь, компилер тебя подстраховывает

хмм ... у меня нет такого. Не сохранил, получи AV или висяк.
Где-то в настройках?


 
SergP ©   (2016-05-31 17:03) [21]


>
> EBX обьектный регистр, который нужно сохранять, видя что
> ты его используешь, компилер тебя подстраховывает


Да, я его использовал, но я сам его сохранял при этом.  
Ну даже пусть он таким образом меня подстраховывает,
но зачем в конце функции мне портить результат, который был в eax, командой mov eax,ebx ?


 
Rouse_ ©   (2016-05-31 17:05) [22]


> dmk ©   (31.05.16 17:01) [20]
> >видя что ты его используешь, компилер тебя подстраховывает
>
> хмм ... у меня нет такого. Не сохранил, получи AV или висяк.
>
> Где-то в настройках?

Хм, на ХЕ10 тоже не сгенерировалось, а вчера на домашней (ХЕ4) был такой код


 
Rouse_ ©   (2016-05-31 17:07) [23]


> SergP ©   (31.05.16 17:03) [21]

Вариантов много, от ошибки генерации кода (судя по всему) до преднамеренно вставляемой инструкции (доки нужно смотреть)


 
SergP ©   (2016-05-31 17:23) [24]


> Rouse_ ©   (31.05.16 17:07) [23]
>
>
> > SergP ©   (31.05.16 17:03) [21]
>
> Вариантов много, от ошибки генерации кода (судя по всему)
> до преднамеренно вставляемой инструкции (доки нужно смотреть)


Но вот в твоем коде [6] оно такого не вставило...

Получается, что после того как написал что-то на асме, нужно ставить бряк, и в окне CPU-View всегда проверять что там компилятор намутил, и если он сделал мне такой подарок, переписывать код по-другому и снова проверять, и так далее, пока его добавления не перестанут противоречить логике работы моего кода?


 
Rouse_ ©   (2016-05-31 17:24) [25]

Вполне вероятно что действительно ошибка, сейчас пересмотрел свои исходные коды, там есть у меня всяческие подстраховки плана:

 function GetSPAddrFromPEB(var Len: Integer): Pointer;
 asm
 {$IFDEF WIN32}
   mov edx, FS:[$30]
   movzx ecx, word ptr [edx + $1F0]
   mov [eax], ecx
   mov eax, [edx + $1F4]
 {$ELSE}
   //  mov rdx, GS:[$60]
   // в старых версиях плывет кодогенерация при работе с сегментами
   // поэтому пропишем опкоды напрямую
   DB $65, $48, $8B, $14, $25, $60, $00, $00, 00
   movzx rax, word ptr [rdx + $2E8]
   mov word ptr [rcx], ax
   mov rax, [rdx + $2F0]
 {$ENDIF}
 end;


 
Rouse_ ©   (2016-05-31 17:24) [26]


> SergP ©   (31.05.16 17:23) [24]
> Получается, что после того как написал что-то на асме, нужно
> ставить бряк, и в окне CPU-View всегда проверять что там
> компилятор намутил, и если он сделал мне такой подарок,
> переписывать код по-другому и снова проверять, и так далее,
>  пока его добавления не перестанут противоречить логике
> работы моего кода?

Конечно, проверять всегда надо - а как по другому-то?


 
Rouse_ ©   (2016-05-31 17:27) [27]

Есть другой вариант.
Оформляй все свои асм блоки как процедуры - тогда получишь чистый код - без пролога и эпилога - тно вызов таких функций нудно контролировать самому


 
Rouse_ ©   (2016-05-31 18:44) [28]


> dmk ©   (31.05.16 17:01) [20]
> >видя что ты его используешь, компилер тебя подстраховывает
>
> хмм ... у меня нет такого. Не сохранил, получи AV или висяк.
>


Да, еще раз перепроверил под ХЕ4

// пролог
005B1FD4: 55                                         PUSH EBP
005B1FD5: 8B EC                                      MOV EBP, ESP
005B1FD7: 53                                         PUSH EBX

// тело функции
005B1FD8: 52                                         PUSH EDX
005B1FD9: 51                                         PUSH ECX
005B1FDA: 53                                         PUSH EBX
005B1FDB: 8B 4C 24 10                                MOV ECX, [ESP+0x10]
005B1FDF: 8B 5C 24 14                                MOV EBX, [ESP+0x14]
005B1FE3: 48                                         DEC EAX
005B1FE4: 3B 5A 04                                   CMP EBX, [EDX+0x4]
005B1FE7: 75 04                                      JNZ 0x5B1FED
005B1FE9: 3B 0A                                      CMP ECX, [EDX]
005B1FEB: 74 06                                      JZ 0x5B1FF3
005B1FED: 83 C2 16                                   ADD EDX, 0x16
005B1FF0: 48                                         DEC EAX
005B1FF1: 79 F1                                      JNS 0x5B1FE4
005B1FF3: 5B                                         POP EBX
005B1FF4: 59                                         POP ECX
005B1FF5: 5A                                         POP EDX

// эпилог
005B1FF6: 8B C3                                      MOV EAX, EBX << оть это весьма странно, видимо инициализация результата
005B1FF8: 5B                                         POP EBX
005B1FF9: 5D                                         POP EBP
005B1FFA: C2 08 00                                   RET 0x8


Здесь явно кривая кодогенерация


 
Rouse_ ©   (2016-05-31 18:46) [29]

Судя по тому что в ХЕ10 такого не наблюдается - значит был на CodeCentral багрепорт и это было исправлено.


 
Pavia ©   (2016-05-31 23:20) [30]

1) Читай справку Parameter passing.
Первые 3 параметра передаются через EAX, EDX, и ECX,  остальные через стек.

2)

> push ebp;    // Зачем делать то, что я не просил?

Это нужно, для отладчика. Принудительно отключается так
procedure Foo(); registers;
assemble
asm
end;
Передача параметров через регистры и убираем begin.


> mov eax,ebx; //Зачем оно мне result портит?

Он вам портит не resul, а eax.
result это локальная переменная в стеке.
При разработке компилятора так проще сделать.


> и еще вопрос: Вроде для таких вещей можно использовать команду
> loop, если бы она работала с 32-разрядным регистром.
>
> Но вот по информации в инете не могу понять: какой все-таки
> регистр использует команда loop :  CX или ECX?


У инструкции, ака мнемоники "loop" есть несколько кодов. По умолчанию в Delphi идет 32 битный или 64 битный в зависимости от настрое компилятора.
В старом паскале был 16 битный.

Для 16 - CX, для 32 , ECX

Код можно принудительно переключить приставкой.
Обычно db 66h, но для Loop db 67h

> Что подразумевается под атрибутом размера адреса?

Есть несколько приставок основных две приставка изменить_размер_данных и приставка изменить_размер_адреса
db 66h и db 67h


> Чем отличаются команды JE от JZ и JNE от JNZ?

Ничем. Помните про луп, тут обратный случай мнемоники разные, а код один.


> и еще: будет ли LEA edx,[edx+step] в данном случае быстрее?

В данном одинаково.


> ?
> и как в будущем предугадать такие козни компилятора?

Алгоритм генерации стековых рамок довольно сложный.

Вот из RTL паскаля 7, что лежало на 13 дискете.


*******************************************************
; *       *
; * MACROS      *
; *       *
; *******************************************************

LOCALS @@

; Public variable definition macro

VAR MACRO Symbol,SType,Count
 PUBLIC Symbol
 Symbol LABEL SType
 IF Count
   DB SType * Count DUP(?)
 ENDIF
ENDM

; Parameter definition macro

ARG MACRO Symbol,SType,Count
 LOCAL Offset
 @AP = @AP + SType * Count
 Offset = @AP
 Symbol EQU (SType PTR [BP+@AF-Offset])
ENDM

@AP = 0
@AF = 0

; Local variables definition macro

LOC MACRO Symbol,SType,Count
 LOCAL Offset
 @LP = @LP + SType * Count
 Offset = @LP
 Symbol EQU (SType PTR [BP+@LF-Offset])
ENDM

@LP = 0
@LF = 0

; Stack frame modifiers

sfFar  EQU 01H  ;FAR frame
sfMarkBP EQU 02H  ;Make saved BP odd
sfSaveDS EQU 04H  ;Save DS at [BP-2]
sfInitDS EQU 08H  ;Init DS using SS

; Default stack frame type

sfDefault = 0

; Stack frame types

   IF WindowsVersion
WINFAR  EQU sfFar+sfMarkBP+sfSaveDS
   ELSE
WINFAR  EQU sfFar
   ENDIF

; Entry code generation macro

ENTRY MACRO FrameType
 IFB <FrameType>
   @SF = sfDefault
 ELSE
   IFIDNI <FrameType>,<NEAR>
     @SF = 0
   ELSE
     IFIDNI <FrameType>,<FAR>
       @SF = sfFar
     ELSE
       @SF = FrameType
     ENDIF
   ENDIF
 ENDIF
 IF @SF AND sfMarkBP
   INC BP
 ENDIF
 PUSH BP
 MOV BP,SP
 IF @SF AND sfFar
   @AF = @AP + 6
 ELSE
   @AF = @AP + 4
 ENDIF
 IF @SF AND sfSaveDS
   PUSH DS
   @LF = -2
 ELSE
   @LF = 0
 ENDIF
 IF @LP
   SUB SP,@LP
 ENDIF
 IF @SF AND sfInitDS
   PUSH DS
   PUSH SS
   POP DS
 ENDIF
ENDM

; Exit code generation macro

EXIT MACRO ArgSize
 IF @SF AND sfInitDS
   POP DS
 ENDIF
 IF @LF - @LP
   MOV SP,BP
 ENDIF
 POP BP
 IF @SF AND sfMarkBP
   DEC BP
 ENDIF
 IFNB <ArgSize>
   @AP = ArgSize
 ENDIF
 IF @SF AND sfFar
   RETF @AP
 ELSE
   RETN @AP
 ENDIF
 @AP = 0
 @LP = 0
ENDM


 
Rouse_ ©   (2016-05-31 23:46) [31]

Эммм...
Pavia, знаешь чем теория отличается от практики? :)

Зы: а так в принципе... Ну ты старался :)


 
Pavia ©   (2016-06-01 08:53) [32]


> Pavia, знаешь чем теория отличается от практики? :)

Знаю.

Просто вчера не смог вспомнить где лежит нужная теория. Сегодня вспомнил.
Полная теория лежит в бумажном руководстве пользователя, а не в хелпе.


> Да, я его использовал, но я сам его сохранял при этом.  
>
> Ну даже пусть он таким образом меня подстраховывает,
> но зачем в конце функции мне портить результат, который
> был в eax, командой mov eax,ebx ?

Да это косяк компилятора. Но программист виноват не меньше.

Assembly procedures and functions


> Unless a function returns a string, variant, or interface
> reference, the compiler doesn"t allocate a function result
> variable; a reference to the @Result symbol is an error.
>  For strings, variants, and interfaces, the caller always
> allocates an @Result pointer.
>


Пока вы в тексте  не напишете @Result компилятор думает, что его нет.
По идее он должен был выкинуть mov eax, ebx. Но не выкинул.

Так что пишите         mov @Result,eax и будет всё тип топ.


 
Pavia ©   (2016-06-01 09:03) [33]

Сейчас свой кодогенератор делаю. Так вот теории нету! Не понятно как гарантировать его безошибочность.
Пока что остановился на следующим пишу частные случае потом буду обобщать на общие. А после тестировать. Но как известно тестирование не гарантирует, что не будет ошибок. Особенно тут с неизвестной выходной функцией.


 
Rouse_ ©   (2016-06-01 10:36) [34]

Ну тогда у тебя не правильные выводы, практически все.
Я не знаю где ты такую документацию читал


> Первые 3 параметра передаются через EAX, EDX, и ECX,  остальные
> через стек.

не верно, если параметр не влазит в регистр он идет принудительно через стек


> Это нужно, для отладчика.

не верно. Отладчику на это сугубо фиолетово, да и программа как правильно работает без отладчика. Это нужно для локальных переменных и параметров.


> Принудительно отключается так
> procedure Foo(); registers;
> assemble
> asm
> end;


не верно.

procedure Foo(); register; assembler;
var
 Tst: DWORD;
asm
 mov eax, 10
 mov Tst, eax
end;


выдаст вот такой код:

004184AC: 55                                         PUSH EBP
004184AD: 8B EC                                      MOV EBP, ESP
004184AF: 51                                         PUSH ECX
004184B0: B8 0A 00 00 00                             MOV EAX, 0xA
004184B5: 89 45 FC                                   MOV [EBP-0x4], EAX
004184B8: 59                                         POP ECX
004184B9: 5D                                         POP EBP
004184BA: C3                                         RET



> Он вам портит не resul, а eax.
> result это локальная переменная в стеке.

не верно, в данном случае Result это именно EAX, а не какая-то переменная на стеке (при чем тут вообще стек)


> Код можно принудительно переключить приставкой.
> Обычно db 66h, но для Loop db 67h


не верно, префикс 0х66 т.н. OperandSizeOverride используется для модификации инструкции (insw->insd/iret->iretd и т.п.) а для модификации регистров используется префикс AddressSizeOverride = $67

вот полный список префиксов:

// служебные префиксы
// см. "2.2. SUMMARY OF INSTRUCTION PREFIXES"
// =============================================================================
type
 TPrefixData = record
   Value: Integer;
   Description: string;
 end;

const
 // Lock and repeat prefixes:
 pfxLock = $F0;
 // The LOCK prefix can be prepended only to the following instructions and only to those forms
 // of the instructions where the destination operand is a memory operand: ADD, ADC, AND,
 // BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR,
 // XADD, and XCHG

 pfxRepn = $F2;
 pfxRep = $F3;

 // Segment override prefixes:
 pfxCSSegmentOverride = $2E;
 pfxSSSegmentOverride = $36;
 pfxDSSegmentOverride = $3E;
 pfxESSegmentOverride = $26;
 pfxFSSegmentOverride = $64;
 pfxGSSegmentOverride = $65;

 // Operand-size override prefix
 // (when used with the escape opcode 0FH, this
 // is treated as a mandatory prefix for some SIMD instructions)
 pfxOperandSizeOverride = $66;
 pfxEscapeOpcode = $0F;

 // Address-size override prefix
 pfxAddressSizeOverride = $67;

 pfxFPU_BFHTRange = $BF;
 pfxFPUOpcodeRange = [$D8..$DF];

 Prefixes: array [0..8] of TPrefixData = (
  (Value: pfxLock; Description: "lock"),
  (Value: pfxRepn; Description: "repn"),
  (Value: pfxRep; Description: "rep"),
  (Value: pfxCSSegmentOverride; Description: "cs:"),
  (Value: pfxSSSegmentOverride; Description: "ss:"),
  (Value: pfxDSSegmentOverride; Description: "ds:"),
  (Value: pfxESSegmentOverride; Description: "es:"),
  (Value: pfxFSSegmentOverride; Description: "fs:"),
  (Value: pfxGSSegmentOverride; Description: "gs:")
 );



> Алгоритм генерации стековых рамок довольно сложный.

не верно - размер стекового фрейма равен общему размеру используемых локальных переменных и передаваемых через стек параметров. ничего секретного и сложного в этом нет.


> Так что пишите         mov @Result,eax и будет всё тип топ.

и получишь на выходе замечательную но бессмысленную инструкцию
MOV EAX, EAX

Вот как-то так вкратце.


 
Игорь Шевченко ©   (2016-06-01 12:05) [35]

http://www.lib.ru/LITRA/CHEHOW/r_letter.txt


 
SergP ©   (2016-06-01 15:01) [36]


> У инструкции, ака мнемоники "loop" есть несколько кодов.
>  По умолчанию в Delphi идет 32 битный или 64 битный в зависимости
> от настрое компилятора.
> В старом паскале был 16 битный.
>
> Для 16 - CX, для 32 , ECX
>
> Код можно принудительно переключить приставкой.
> Обычно db 66h, но для Loop db 67h


Так это приставка действует только на следующую за ней команду loop или переключает глобально?
И почему через db? Ей, что, забыли придумать отдельную мнемонику?


 
Rouse_ ©   (2016-06-01 15:27) [37]


>
> Так это приставка действует только на следующую за ней команду
> loop или переключает глобально?

да, это префикс для идущей за ней инструкции, модифицирующий ее поведение по умолчанию


> И почему через db? Ей, что, забыли придумать отдельную мнемонику?

может и есть, но я не в курсе. (может какой нить "short loop" или еще как нибудь)


 
Pavia ©   (2016-06-01 16:18) [38]


> Так это приставка действует только на следующую за ней команду
> loop или переключает глобально?
> И почему через db? Ей, что, забыли придумать отдельную мнемонику?
>

Да, только на следующую. Для приставки отдельную мнемонику не стали делать. Обычно используется PTR или суффикс d, но вот loop это исключение. Интел толком не описывал. Сейчас вроде придерживатся борладского стиля. Но для каждого компилятора надо выяснять отдельно.


> The loop instructions for the 80386 processor can either
> use CX or ECX as the counting
> register. The standard LOOP, LOOPE, LOOPZ, LOOPNE, and LOOPNZ
> mnemonics
> from Intel select the counting register based on whether
> the current code segment is a 32-bit segment (when using
> ECX) or a 16-bit segment (when using CX).
> Turbo Assembler has special instructions that increase the
> flexibility of the LOOP
> feature. The LOOPW, LOOPWE, LOOPWZ, LOOPWNE, and LOOPWNZ
> instructions
> use CX as the counting register, regardless of the size
> of the current segment. Similarly, the LOOPD, LOOPDE, LOOPDZ,
>  LOOPDNE, and LOOPDNZ instructions use ECX as the counting
> register


 
Pavia ©   (2016-06-01 16:41) [39]


> > Это нужно, для отладчика.
>
> не верно. Отладчику на это сугубо фиолетово, да и программа
> как правильно работает без отладчика. Это нужно для локальных
> переменных и параметров.

Отладчику не всё равно! Смотри скриншот. XE5 Настройки стандартные.
http://s33.postimg.org/p7tfcr7jj/image.png


 
Rouse_ ©   (2016-06-01 16:59) [40]


> Pavia ©   (01.06.16 16:41) [39]

Ну так это же настройки компилятора, а не отладчика :)



Страницы: 1 2 3 вся ветка

Форум: "Прочее";
Текущий архив: 2017.08.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.6 MB
Время: 0.003 c
2-1426143698
Atamali Memmedov
2015-03-12 10:01
2017.08.27
Exception


1-1352975235
yurikon
2012-11-15 14:27
2017.08.27
Доступ к массиву по ключу


2-1427276393
Ega23
2015-03-25 12:39
2017.08.27
Передача массива вариантов в функцию


3-1314713126
tomkat
2011-08-30 18:05
2017.08.27
Экранировать % в FireBird


4-1283282748
Sam Bellamy
2010-08-31 23:25
2017.08.27
активирование приложения, SDI





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский