Unit can't get value from other unit lazarus / 9-Editor ---------------------------------------------------------------------- Paul-SFL · 2011-11-05 20:54 Hi all, I'm asking for someone's help 'cause I've already got mad trying to solve my problem . I'm working on a program which emulates a simple processor. It consists of several units. All variables are placed into separate unit, another unit is the emulator itself and the third one is a form where I need to output contents of the processor's "registers" to on each step of emulation. Emulator is 100% working. The problem is that when I try to output the data it doesn't work properly - form's field where I put value of register variable to gets wrong value. I don't know what information is necessary and what's not.. Here is code which outputs the value from one of registers: Code: [Select]procedure ]"]>Blockedlator_mode.traceClick(Sender: TObject); //emulgui's procedure var CRstring:bstring    ; begin   step; //performs one emulation step; testprocessing's procedure   Set2Str(TCV.CR,CRstring); //converts set to string; testprocessing's procedure   emulator_mode.CR.Caption:=CRstring; //moves string to TLabeledEdit's caption end; I guess maybe I made a mistake in units referrence.. Here it is: Code: [Select]unit emulgui //window where I need to output data interface uses tcv //unit where all variables, types and constants are implementation uses testprocessing //emulation unit Code: [Select]unit testprocessing interface uses tcv; implementation uses emulguiIs that right? Using Lazarus 0.9.30 wih FPC 2.4.2 on Windows 7 Professional. ---------------------------------------------------------------------- Blaazen · 2011-11-05 21:08 I can't see anything wrong with your code snippets. Quote- form's field where I put value of register variable to gets wrong value. What it means "wrong value" ? Is it empty, bad format or ... ? ---------------------------------------------------------------------- Paul-SFL · 2011-11-05 21:26 Wrong means value that shouldn't be there. CR.Caption must get certain values - they're in txt file. The value CR.Caption gets is not present in that file.. Txt file includes strings with quaternary numbers (they mean commands and numbers). Testprocessing unit reads them, converts to strings with binary numbers, then to sets, then moves them to RAM variable (array of sets). Procedure TestLoading which performs all this is called from emulgui unit on form create. In Step procedure program reads next set from RAM to CR (set variable), then performs some (depends on CR value) processor's operation emulation. ---------------------------------------------------------------------- Leledumbo · 2011-11-06 01:54 Then we need to see Step and Set2Str implementation. Or you could place a breakpoint: Code: [Select]procedure ]"]>Blockedlator_mode.traceClick(Sender: TObject); //emulgui's procedure var CRstring:bstring    ; begin   step; //performs one emulation step; testprocessing's procedure (* PUT BREAKPOINT HERE *)  Set2Str(TCV.CR,CRstring); //converts set to string; testprocessing's procedure   emulator_mode.CR.Caption:=CRstring; //moves string to TLabeledEdit's caption end;and inspect the changes yourself. ---------------------------------------------------------------------- Paul-SFL · 2011-11-06 07:21 Oh, I'm not very familiar with breakpoints and Lazarus debugger on the whole.. Here is procedures implementation: Code: [Select]Unit testprocessing; {$mode objfpc}{$H+} Interface Uses tcv; procedure Set2Str(Const Word_:set_14; Var NewStr:bstring); procedure TestLoading(TestNum:byte); procedure Step; procedure OpCodeDC; procedure CRDC; Procedure CommandLoading; procedure g1halt; procedure g1load; procedure g1save; procedure g1add; procedure g1sub; procedure g1mul; procedure g1div; procedure g1subm; procedure g1and; procedure g1or; procedure g1xor; procedure g1inc; procedure Bin2Qua(Const BinNum:bstring; Var QuaNum:qstring); procedure Qua2Bin(Const QuaNum:qstring; Var BinNum:bstring); procedure Bin2Dec(Const BinNum:bstring; Var DecNum:dstring); procedure Dec2Bin(Const DecNum:dstring;Var BinStr:bstring); procedure Str2Set(Const Str:bstring; Var NewWord:set_14); procedure Dec2Set(DecNum:integer; Var Set_:set_14); procedure Set2Dec(Set_:set_14; Var DecNum:integer); procedure Set_8ToSet_14(Const R:set_8; Var Set8Converted:set_14); procedure Set_14ToSet_8(Const R:set_14; Var Set14Converted:set_8); procedure AR2Dec; Implementation Uses emulgui; Procedure Set2Str(Const Word_:set_14; Var NewStr:bstring); Var   i:byte; Begin   NewStr:='00000000000000';   For i:=1 to BinNumLen do     If i in Word_ then       NewStr[i]:='1' End { Set2Str }; { ========================== } Procedure TestLoading(TestNum:byte); Var   Test :text;   Code:integer;   RawSA:string[3];   QuaStr:qstring;   BinStr:bstring;   NewWord:set_14;   i:byte; Begin   If Test1Loaded then //procedure is temporary tied to the test №1     Exit;   Case TestNum of     1 : Assign(Test,'test1.txt');     2 : Assign(Test,'test2.txt');     3 : Assign(Test,'test3.txt');   End;   Reset(Test);   Readln(Test,RawSA);   Val(RawSA,SA,Code);   RAM[0]:=[];   i:=1;   While not EoF(Test) do     Begin       Readln(Test,QuaStr);       Qua2Bin(QuaStr,BinStr);       Str2Set(BinStr,NewWord);       RAM[i]:=NewWord;       Inc(i)     End;   Close(Test);   Case TestNum of     1 : Begin           Test1Size:=i-1;           Test1Loaded:=true;           Test2Loaded:=false;           Test3Loaded:=false         End;     2 : Begin           Test2Size:=i-1;           Test1Loaded:=false;           Test2Loaded:=true;           Test3Loaded:=false         End;     2 : Begin           Test3Size:=i-1;           Test1Loaded:=false;           Test2Loaded:=false;           Test3Loaded:=true         End;   End;   SAinIP:=false; End { TestLoading }; { ========================== } Procedure CommandLoading; Var   Buf  :set_14;   var crc:bstring    ; Begin   If not SAinIP then     Begin       Buf:=[];       Dec2Set(SA,Buf);       Set_14ToSet_8(Buf,IP);       SAinIP:=true     End;   AR:=IP;      Set_8ToSet_14(AR,Buf);   Set2Dec(Buf,ARVal);   WR:=RAM[ARVal];   CR:=WR        ; End { CommandLoading }; { ========================== } Procedure CRDC; Var   i:byte; Begin    With CRDecoded do     Begin       OpCode:='0000';       DestRegister:=0;       AddrMode:=0;       Address:='00000000000000';       For i:=1 to 4 do         If i in CR then           OpCode[i]:='1';       If 5 in CR then         Inc(DestRegister);       If 6 in CR then         Inc(AddrMode);       For i:=7 to BinNumLen do         If i in CR then           Address[i]:='1'     End;   g1Inc End { CRDC }; { ========================== } Procedure OpCodeDC; Var   OpCode,   Code    :integer; Begin   Val(CRDecoded.OpCode,OpCode,Code);   Case OpCode of      0 : G1Halt;      1 : G1Load;      10 : G1Save;      11 : G1Add;      100 : G1Sub;      101 : G1Mul;      110 : G1Div;      111 : G1Subm;      1000 : G1And ;      1001 : G1Or  ;     1010 : G1Xor ;     1011 : G1Inc ;     (*1100 : JS_  ;     1101 : JZ_  ;     1110 : Jump_;     1111 : Call_*)   End End { OpCodeDC }; { ========================== } Procedure Step; Begin CommandLoading; CRDC; OpCodeDC; End { Step }; { ========================== } End. Hmm, just tried to run debugger (pressing F8) and got an error saying "Project gui1.exe called exeption class 'External: SIVSEGV'... ---------------------------------------------------------------------- User137 · 2011-11-06 08:05 Is BinNumLen a constant value 14? Counted 14 zeroes in NewStr... Propably helps showing also set_14 type definition. ---------------------------------------------------------------------- Paul-SFL · 2011-11-06 08:42 Yes, BinNumLen is constant value 14 Code: [Select]Type   fourteen_elems=1..14;   set_14=set of fourteen_elems; ---------------------------------------------------------------------- User137 · 2011-11-06 09:08 Code: [Select]var s: string; w: set_14; begin   s:='';   w:=[6,5,3,13,14, 15,0,-6,99]; // Add 5 bits and some extras outside range   Set2Str(w, s); // Now s = '00101100000011'; which seems correct Could it be that values themselves that are delivered to Set2Str() are wrong? ---------------------------------------------------------------------- Paul-SFL · 2011-11-06 09:25 No, it doesn't seems to be so. All procedures have been tested many times.  Set2Str() checks only correct values (1..14), so output string cannot include wrong values: Code: [Select]  NewStr:='00000000000000';   For i:=1 to BinNumLen do //i gets only values from 1 to 14     If i in Word_ then       NewStr[i]:='1' Generally speaking, the program is being written in purpose that all input data is correct. ---------------------------------------------------------------------- Leledumbo · 2011-11-06 13:14 QuoteHmm, just tried to run debugger (pressing F8) and got an error saying "Project gui1.exe called exeption class 'External: SIVSEGV'...Then you're one of people who get problem with the debugger, happily search the forum. The cause varies, though. If you're not familiar with the debugger, you can use 'old ways' of debugging: put ShowMessage on curious points (loops, branches, etc), displaying the contents of variables whose value seems not right. ---------------------------------------------------------------------- Paul-SFL · 2011-11-06 13:55 Leledumbo, thanks, I get it. I'll try.. ---------------------------------------------------------------------- Paul-SFL · 2011-11-11 15:47 Oh, guys, what a stupid mistake I made ... Testprocessing unit was tested in Turbo Pascal (as I'm yet not very familiar with FPC), and I tested it as a single program, without separating to units. When I started adding Testprocessing and TCV to Lazarus project, I simply copypasted code (unit declaration, to be exact) from emulgui, and there this string was: Code: [Select]{$mode objfpc}{$H+} The solution was replacing {$mode objfpc} with {$mode tp} in Testprocessing and TCV units. Thank all for your advice .