Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 4 493

Раздел: Ассемблер
/ вопрос открыт /

Привет всем.
Мой вопрос заключается в ошибке под названием Internal error: L3118
Суть в том что я пытаюсь получить значение регистра ESI путем прикрепления obj файла к проекту и вызовом соответствующих функций. Сам регистр я не изменяю. Почему возникает ошибка уже второй день понять не могу, но подозреваю что из за работы с ESI.

К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)

Приложение:
  1. Unit1.pas
  2. **********************************************************
  3. unit Unit1;
  4.  
  5. interface
  6.  
  7. uses
  8. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  9. Dialogs, StdCtrls;
  10.  
  11. type
  12. TForm1 = class(TForm)
  13. Label1: TLabel;
  14. Label4: TLabel;
  15. Button2: TButton;
  16. procedure Button2Click(Sender: TObject);
  17. private
  18. { Private declarations }
  19. public
  20. { Public declarations }
  21. end;
  22.  
  23. Procedure EsiNum();STDCall;EXTERNAL;
  24. Procedure WordIn();STDCall;EXTERNAL;
  25. {$L StackOut1}
  26.  
  27. var
  28. Form1: TForm1;
  29. ESIV: DWord;
  30.  
  31. implementation
  32.  
  33. {$R *.dfm}
  34.  
  35.  
  36. procedure TForm1.Button2Click(Sender: TObject);
  37. begin
  38. EsiNum();
  39. Label1.Caption:=IntToStr(ESIV);
  40. WordIn();
  41. Label4.Caption:=IntToStr(ESIV);
  42. end;
  43.  
  44. end.
  45.  
  46. ***********************************************************
  47.  
  48. StackOut1.asm
  49. ***********************************************************
  50. Title StackOut for 32 bit
  51. .486P
  52. .MODEL flat, STDCall
  53.  
  54.  
  55. ;PUBLIC StackOut
  56. PUBLIC WordIn
  57. PUBLIC ESINUM
  58.  
  59. .Data
  60. EXTRN ESIV: DWORD
  61.  
  62. a32 DD ?
  63. b32 DD ?
  64. c32 DD ?
  65. d32 DD ?
  66.  
  67. .CODE
  68.  
  69. WordIn proc
  70. mov a32,eax
  71. mov eax,110
  72. push ax
  73. push esi
  74. pop eax
  75. mov ESIV,eax
  76. pop ax
  77. mov eax,a32
  78. ret
  79. WordIn ENDP
  80.  
  81.  
  82.  
  83. ESINUM proc
  84. mov a32,eax
  85. push esi
  86. pop eax
  87. mov ESIV,eax
  88. mov eax,a32
  89. ret
  90. ESINUM ENDP
  91.  
  92. END
  93. ************************************************************


SOA Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: SOA (статус: Посетитель)
Вопрос отправлен: 8 августа 2010, 14:10
Состояние вопроса: открыт, ответов: 1.

Ответ #1. Отвечает эксперт: Вадим К

Здравствуйте, SOA!
Смотрим на название ошибки "Internal error: L3118". Первая часть говорит, что это какая то непредвиденная ошибка. Дальше есть буква L - это значит ошибка линковки, ну а дальше некий номер, по которому можно разработчикам компилятора сообщить.
Часто такие ошибки бывают из-за того, что программист пытается обхитрить компилятор.
Так как в нашем случае возникает ошибка линковки, то скорее всего полученный obj файл не совсем верный. Если этот файл получен с помощью компилятора TASM или MASM, а версия делфи старше третьей - то это и будет причиной, так как не совместимы эти файлы.
Если же obj файл получен третьими инструментами (например VisualStudio), то слинковать его вряд ли получиться.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 8 августа 2010, 18:04
Оценка за ответ: 5

Комментарий к оценке: Спасибо за предложенный вариант передачи данных из delphi в асм.

Мини-форум вопроса

Всего сообщений: 21; последнее сообщение — 17 августа 2010, 13:43; участников в обсуждении: 2.

Страницы: [1] [2] [Следующая »]

SOA

SOA (статус: Посетитель), 8 августа 2010, 15:45 [#1]:

Произошла ошибка регистр не ESI а ESP.
Вот правильный код(в смысле с правильным регистром, но попрежнему нерабочий =()

Unit1.pas
*******************************************
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label4: TLabel;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
Procedure EspNum();STDCall;EXTERNAL;
Procedure WordIn();STDCall;EXTERNAL;
{$L StackOut1}
 
var
  Form1: TForm1;
  ESPV: DWord;
 
implementation
 
{$R *.dfm}
 
 
procedure TForm1.Button2Click(Sender: TObject);
begin
EspNum();
Label1.Caption:=IntToStr(ESPV);
WordIn();
Label4.Caption:=IntToStr(ESPV);
end;
 
end.
***************************************************

StackOut1.asm
***************************************************
Title StackOut for 32 bit
.486P
.MODEL flat, STDCall
 
 
;PUBLIC StackOut
PUBLIC WordIn
PUBLIC EspNum
 
.Data
EXTRN ESPV: DWORD
 
a32 DD ?
b32 DD ?
c32 DD ?
d32 DD ?
 
.CODE
 
WordIn proc
mov a32,eax
mov eax,110
push ax
push esp
pop eax
mov ESPV,eax
pop ax
mov eax,a32
ret
WordIn ENDP
 
 
 
EspNum proc
mov a32,eax
push esp
pop eax
mov ESPV,eax
mov eax,a32
ret
EspNum ENDP
 
END
*******************************************
SOA

SOA (статус: Посетитель), 8 августа 2010, 18:12 [#2]:

Здравствуйте Вадим К:
Компилируется в Tasm, версия подходящая, вот этот пример например компелируется очень легко
Title move for 32 bits
 
.386P
.MODEL  FLAT, stdcall
PUBLIC Movl
 
.DATA
extrn x:DWORD
a DD 64h
 
.CODE
Movl  proc
mov ax,WORD PTR a  ;ax<=== мл. часть a
push bx
mov bx,WORD PTR a+2  ;bx<=== ст. часть a
mov WORD PTR x,ax  ;мл. часть x<=== ax
mov WORD PTR x+2,bx  ;ст. часть x<=== bx
pop bx
ret
Movl  ENDP
 
END
Все линкуется и т.д.

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

P.S. по версиям masm и tasm у них просто начиная с 3 верси masm и tasm форматы obj файлов не совпадают, из за чего языки программирования borland'а понимают только obj файлы tasm а masm'овские можно прилинковать только если версия masm не выше 3 (во всяком случае я такую инфу читал) 8/
SOA

SOA (статус: Посетитель), 9 августа 2010, 04:16 [#3]:

Что самое интересное такой код

Title StackOut for 32 bit
.486P
.MODEL flat, STDCall
 
 
;PUBLIC StackOut
PUBLIC WordIn
PUBLIC EspNum
 
.Data
EXTRN ESPV: DWORD
 
a32 DD ?
b32 DD ?
c32 DD ?
d32 DD ?
 
.CODE
 
WordIn proc
;mov a32,eax
;mov eax,110
push ax
;push esp
;pop eax
;mov ESPV,eax
mov ESPV,esp
pop ax
;mov eax,a32
ret
WordIn ENDP
 
 
 
EspNum proc
;mov a32,eax
;push esp
;pop eax
;mov ESPV,eax
;mov eax,a32
mov ESPV,ESP
ret
EspNum ENDP
 
END
 
компилируется и линкуется легко, хотя если сравнивать с первым кодом то делают фактически то же самое, но первый почему
то не линкуется с проектом в delphi =(
Вадим К

Вадим К (статус: Академик), 9 августа 2010, 10:06 [#4]:

Посмотрел код. Думаю что вся проблема возникает из за переменной ESPV, которую пытаетесь расшарить между двумя модулями. В принципе, никто не мешает возвращать результат в регистре eax - вот и возвращайте:)

Где то Вы пытаетесь обмануть линковщик с компилятором. Только вот где - пока не понятно.
Галочка "подтверждения прочтения" - вселенское зло.
SOA

SOA (статус: Посетитель), 9 августа 2010, 10:33 [#5]:

В моем случае переменные типа ESPV это необходимость т.к. они помогают передавать параметры в процедуры из obj файлов на асм, хотя конечно можно использовать стэк, но при попытке использования вылетала либо такая же ошибка, либо ошибка обращения по неверному адресу, поэтому для изучения особенностей взаимодействия в стеке основной программы и кода obj файла, я и попытался написать такой код, который в результате тоже начал ругаться по не выясненной пока причине.

За eax спасибо, как то не подумал :)
только боюсь как бы не возникло спецэффектов, но люди вроде бы пишут что в delphi можно свободно изменять eax,ecx,edx.
Вадим К

Вадим К (статус: Академик), 9 августа 2010, 11:27 [#6]:

eax в делфи используется для того, что бы возвращать результат. Также никто не мешает передавать через него данные.
А глобальные переменные в большинстве своем - зло.
Галочка "подтверждения прочтения" - вселенское зло.
SOA

SOA (статус: Посетитель), 9 августа 2010, 12:55 [#7]:

Про eax буду знать.
А без глобальных переменных порой просто не обойтись.
Вадим К

Вадим К (статус: Академик), 9 августа 2010, 13:21 [#8]:

думаю, данный код можно переделать так - создать функцию, которая будет возвращать адрес этой переменной. Таким образом решается проблема глобальной переменной.
Галочка "подтверждения прочтения" - вселенское зло.
SOA

SOA (статус: Посетитель), 10 августа 2010, 19:42 [#9]:

Не получилось =(
В этом коде переменная из дельфи не объявляется, а берется ее адрес, по которому потом помещается значение регистра esp, но всеравно возникает ошибка линковки.

Unit1.pas
*****************************************************
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label4: TLabel;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
PROCEDURE ESPVIN(p:pointer);
Procedure EspNum();STDCall;EXTERNAL;
Procedure WordIn();STDCall;EXTERNAL;
{$L StackOut1}
 
var
  Form1: TForm1;
  ESPV: DWord;
 
implementation
 
{$R *.dfm}
 
 
procedure TForm1.Button2Click(Sender: TObject);
begin
ESPVIN(@ESPV);
EspNum();
Label1.Caption:=IntToStr(ESPV);
WordIn();
Label4.Caption:=IntToStr(ESPV);
end;
 
PROCEDURE ESPVIN(p:pointer);
Begin
 asm
 mov eax,p
 end;
 
End;
 
end.

***************************************************

StackOut1.asm
***************************************************
Title StackOut for 32 bit
.486P
.MODEL flat, STDCall
 
 
;PUBLIC StackOut
PUBLIC WordIn
PUBLIC EspNum
 
.Data
StackV DWORD ?
 
a32 DD ?
b32 DD ?
c32 DD ?
d32 DD ?
 
.CODE
 
WordIn proc
mov a32,eax  ; просто так
push ax    ; смещаем вершину стека
mov [eax],esp
pop ax    ; возвращаем начальное значение вершине стека
mov eax,a32  ; просто так
ret
WordIn ENDP
 
 
 
EspNum proc
mov a32,eax  ; просто так
mov [eax],esp
mov eax,a32  ; просто так
ret
EspNum ENDP
 
END

****************************************************
Вадим К

Вадим К (статус: Академик), 11 августа 2010, 11:51 [#10]:

смотрим эту процедуру
PROCEDURE ESPVIN(p:pointer);
Begin
 asm
 mov eax,p
 end;
 
End;
В ней указатель записывается в регистр eax. И какой смысл с этого кода?
Во вторых, я писал в IRC, что нужно не ESPV: DWord;, а
ESPV: ^DWord;
Галочка "подтверждения прочтения" - вселенское зло.
SOA

SOA (статус: Посетитель), 11 августа 2010, 13:26 [#11]:

Здравствуйте Вадим К:
Если я все правильно понял вы имели ввиду что нужно сделать вот так

Unit1.pas
****************************************************
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label4: TLabel;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
Procedure EspIn();
Procedure EspNum();STDCall;EXTERNAL;
Procedure WordIn();STDCall;EXTERNAL;
Procedure ESPVP();STDCall;EXTERNAL;
{$L StackOut1}
 
var
  Form1: TForm1;
  ESPV: DWord;
  P: pointer;
 
implementation
 
{$R *.dfm}
 
 
procedure TForm1.Button2Click(Sender: TObject);
begin
ESPVP();
EspIn();
EspNum();
Label1.Caption:=String(^P);
WordIn();
Label4.Caption:=String(^P);
end;
 
Procedure EspIn(); // сохраняем указатель на переменную ESPV из модуля asm в переменную p
Begin
 asm
 mov p,eax
 end;
End;
 
 
end.
**************************************************

StackOut1.asm

**************************************************
Title StackOut for 32 bit
.486P
.MODEL flat, STDCall
 
 
;PUBLIC StackOut
PUBLIC WordIn
PUBLIC EspNum
PUBLIC ESPVP
 
.Data
ESPV DWORD ?
 
a32 DD ?
b32 DD ?
c32 DD ?
d32 DD ?
 
.CODE
 
WordIn proc
mov a32,eax  ; просто так
push ax    ; просто так
mov ESPV,esp
pop ax    ; просто так
mov eax,a32  ; просто так
ret
WordIn ENDP
 
 
 
EspNum proc
mov a32,eax  ; просто так
mov ESPV,esp
mov eax,a32  ; просто так
ret
EspNum ENDP
 
ESPVP proc
lea eax,ESPV ; помещаем в eax указатель на ESPV из модуля asm
ret
ESPVP ENDP
 
 
 
END
***********************************************

Так тоже возникает ошибка линковки:(
Вадим К

Вадим К (статус: Академик), 11 августа 2010, 13:43 [#12]:

ESPVP proc
lea eax,ESPV ; помещаем в eax указатель на ESPV из модуля asm
ret
ESPVP ENDP
а никто не гарантировал, что eax останеться по выходу с процедуры.
Но если в делфовском коде объявить как
function ESPVP():pointer;stdcall;
То должно работать такое
p := ESPVP();
writeln(p^);
Галочка "подтверждения прочтения" - вселенское зло.
SOA

SOA (статус: Посетитель), 11 августа 2010, 14:19 [#13]:

Unit1.pas
****************************************************
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label4: TLabel;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
//Procedure EspIn();
Procedure EspNum();STDCall;EXTERNAL;
Procedure WordIn();STDCall;EXTERNAL;
Function ESPVP():pointer;STDCall;EXTERNAL;
{$L StackOut1}
 
var
  Form1: TForm1;
  ESPV: DWord;
  P: pointer;
 
implementation
 
{$R *.dfm}
 
 
procedure TForm1.Button2Click(Sender: TObject);
begin
p:=ESPVP();
EspNum();
Label1.Caption:=String(^P);
WordIn();
Label4.Caption:=String(^P);
end;
 
 
end.
*****************************************************

StackOut1.asm
*****************************************************
Title StackOut for 32 bit
.486P
.MODEL flat, STDCall
 
 
;PUBLIC StackOut
PUBLIC WordIn
PUBLIC EspNum
PUBLIC ESPVP
 
.Data
ESPV DWORD ?
 
a32 DD ?
b32 DD ?
c32 DD ?
d32 DD ?
 
.CODE
 
WordIn proc
mov a32,eax  ; просто так
push ax    ; просто так
mov ESPV,esp
pop ax    ; просто так
mov eax,a32  ; просто так
ret
WordIn ENDP
 
 
 
EspNum proc
mov a32,eax  ; просто так
mov ESPV,esp
mov eax,a32  ; просто так
ret
EspNum ENDP
 
ESPVP proc
lea eax,ESPV
ret
ESPVP ENDP
 
 
 
END
**********************************************

Так тоже не работает.
Вадим К

Вадим К (статус: Академик), 11 августа 2010, 14:35 [#14]:

Не работает или не компилируется/линкуется? это две большие разницы!
Галочка "подтверждения прочтения" - вселенское зло.
SOA

SOA (статус: Посетитель), 11 августа 2010, 14:50 [#15]:

Везде где я писал что код не работает - не происходит линковка obj файла с проектом delphi и вылазит ошибка L3118.
Вадим К

Вадим К (статус: Академик), 11 августа 2010, 15:22 [#16]:

с делфовского кода нужно убрать ESPV: DWord;
Галочка "подтверждения прочтения" - вселенское зло.
SOA

SOA (статус: Посетитель), 11 августа 2010, 15:50 [#17]:

Даже если в Delphi закомментировать переменную ESPV, это все равно не помогает. Проект как не линковался, так и не линкуется - просто линковщик взбесился :)
Вадим К

Вадим К (статус: Академик), 11 августа 2010, 16:18 [#18]:

можно конечно ещё поудалять dcu файлы и подобные нагенерированые делфи и снова собрать проект.
Галочка "подтверждения прочтения" - вселенское зло.
SOA

SOA (статус: Посетитель), 11 августа 2010, 17:25 [#19]:

Бесполезно, линковщику явно что то не нравится в obj файле, потому что когда в подобной ситуации полностью комментируешь процедуру, которая "не нравится линковщику", то все линкуется. Можно конечно методом исключения строчка за строчкой выискивать в asm файле инструкцию, или переменную, которая "не нравится линковщику", как то изменять исходный код, в asm файле чтоб линковщик слинковал проект, но если такие ошибки появляются в большем коде, то устранить их уже становится проблематично таким способом.
Если узнаю как преодолеть эту ошибку отпишу в этом минифоруме.
SOA

SOA (статус: Посетитель), 17 августа 2010, 13:15 [#20]:

Решение найдено нужно было инициализировать переменные в асм коде
.Data
EXTRN ESIV: DWORD
 
a32 DD 0
b32 DD 0
c32 DD 0
d32 DD 0

Страницы: [1] [2] [Следующая »]

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:45
Выполнено за 0.08 сек.