|
Вопрос # 4 493/ вопрос открыт / |
|
Привет всем.
Мой вопрос заключается в ошибке под названием Internal error: L3118
Суть в том что я пытаюсь получить значение регистра ESI путем прикрепления obj файла к проекту и вызовом соответствующих функций. Сам регистр я не изменяю. Почему возникает ошибка уже второй день понять не могу, но подозреваю что из за работы с ESI.
К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)
Приложение: Переключить в обычный режим- 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 EsiNum();STDCall;EXTERNAL;
- Procedure WordIn();STDCall;EXTERNAL;
- {$L StackOut1}
-
- var
- Form1: TForm1;
- ESIV: DWord;
-
- implementation
-
- {$R *.dfm}
-
-
- procedure TForm1.Button2Click(Sender: TObject);
- begin
- EsiNum();
- Label1.Caption:=IntToStr(ESIV);
- WordIn();
- Label4.Caption:=IntToStr(ESIV);
- end;
-
- end.
-
- ***********************************************************
-
- StackOut1.asm
- ***********************************************************
- Title StackOut for 32 bit
- .486P
- .MODEL flat, STDCall
-
-
- ;PUBLIC StackOut
- PUBLIC WordIn
- PUBLIC ESINUM
-
- .Data
- EXTRN ESIV: DWORD
-
- a32 DD ?
- b32 DD ?
- c32 DD ?
- d32 DD ?
-
- .CODE
-
- WordIn proc
- mov a32,eax
- mov eax,110
- push ax
- push esi
- pop eax
- mov ESIV,eax
- pop ax
- mov eax,a32
- ret
- WordIn ENDP
-
-
-
- ESINUM proc
- mov a32,eax
- push esi
- pop eax
- mov ESIV,eax
- mov eax,a32
- ret
- ESINUM ENDP
-
- END
- ************************************************************
 |
Вопрос задал: 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 (статус: Посетитель), 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 (статус: Посетитель), 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 (статус: Посетитель), 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 (статус: Посетитель), 9 августа 2010, 10:33 [#5]:
В моем случае переменные типа ESPV это необходимость т.к. они помогают передавать параметры в процедуры из obj файлов на асм, хотя конечно можно использовать стэк, но при попытке использования вылетала либо такая же ошибка, либо ошибка обращения по неверному адресу, поэтому для изучения особенностей взаимодействия в стеке основной программы и кода obj файла, я и попытался написать такой код, который в результате тоже начал ругаться по не выясненной пока причине.
За eax спасибо, как то не подумал 
только боюсь как бы не возникло спецэффектов, но люди вроде бы пишут что в delphi можно свободно изменять eax,ecx,edx.
|
|
Вадим К (статус: Академик), 9 августа 2010, 11:27 [#6]:
eax в делфи используется для того, что бы возвращать результат. Также никто не мешает передавать через него данные.
А глобальные переменные в большинстве своем - зло.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
SOA (статус: Посетитель), 9 августа 2010, 12:55 [#7]:
Про eax буду знать.
А без глобальных переменных порой просто не обойтись.
|
|
Вадим К (статус: Академик), 9 августа 2010, 13:21 [#8]:
думаю, данный код можно переделать так - создать функцию, которая будет возвращать адрес этой переменной. Таким образом решается проблема глобальной переменной.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
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 (статус: Посетитель), 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 (статус: Посетитель), 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 (статус: Посетитель), 11 августа 2010, 14:50 [#15]:
Везде где я писал что код не работает - не происходит линковка obj файла с проектом delphi и вылазит ошибка L3118.
|
|
Вадим К (статус: Академик), 11 августа 2010, 15:22 [#16]:
с делфовского кода нужно убрать ESPV: DWord;
Галочка "подтверждения прочтения" - вселенское зло.
|
|
SOA (статус: Посетитель), 11 августа 2010, 15:50 [#17]:
Даже если в Delphi закомментировать переменную ESPV, это все равно не помогает. Проект как не линковался, так и не линкуется - просто линковщик взбесился
|
|
Вадим К (статус: Академик), 11 августа 2010, 16:18 [#18]:
можно конечно ещё поудалять dcu файлы и подобные нагенерированые делфи и снова собрать проект.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
SOA (статус: Посетитель), 11 августа 2010, 17:25 [#19]:
Бесполезно, линковщику явно что то не нравится в obj файле, потому что когда в подобной ситуации полностью комментируешь процедуру, которая "не нравится линковщику", то все линкуется. Можно конечно методом исключения строчка за строчкой выискивать в asm файле инструкцию, или переменную, которая "не нравится линковщику", как то изменять исходный код, в asm файле чтоб линковщик слинковал проект, но если такие ошибки появляются в большем коде, то устранить их уже становится проблематично таким способом.
Если узнаю как преодолеть эту ошибку отпишу в этом минифоруме.
|
|
SOA (статус: Посетитель), 17 августа 2010, 13:15 [#20]:
Решение найдено нужно было инициализировать переменные в асм коде
.Data
EXTRN ESIV: DWORD
a32 DD 0
b32 DD 0
c32 DD 0
d32 DD 0
|
Страницы: [1] [2] [Следующая »]
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|