[T.Pascal7]BIOS pristup na disketu alias "AX nie je AH!

C++, C#, Visual Basic, Delphi, Perl a ostatní

Moderátor: Moderátoři Živě.cz

Odeslat příspěvekod inflater 27. 7. 2006 15:17

Caute,
chcel by som sa spytat, ako dostanem z AX hodnotu AL v Borland Pascal 7, bloky ASM-END.
Totizto, cital som ze AX sa deli na AH a AL.
Uz do toho IDE cumakujem hodinu a stale ma nic nenapada :mrgreen:
Nemozem ale zapisat:

asm
...bla bla bla...
int 13h (v AH je navratovy kod)
mov ah, offset ErrSt (chcel by som do "ErrSt", co je typ INTEGER, zapisat hodnotu AH, ale kompiler nevezme)
end;


ale mozem

asm
...bla bla bla...
int 13h
mov high ax, offset ErrSt
end;


a to kompiler vezme, ale nefunguje navratova hodnota (stale 0 aj ked nastala chyba). Dole je ustrizok.
Je to z toho OS, chcel som naprogramovat RawWrite a RawRead funkcie, co by fyzicky zapisovali a citali sektory.
Niektore otestovane a riadne funkcne procedury (napr. Beep, Restart...) som kvoli setreniu miesta vynechal.
(pouzival som ATHELP, schvalne som chcel vyvolat chybu vysunutim diskety a nezobrazilo chybu)

Kód: Vybrat vše
var
ErrSt: Integer;
ErrStStr: String;
InterruptCall: String;
FunctionCall: String;
PopisErr: String;
ReadBuf: array [0..512] of Byte;

const CRLF = #13#10;

function ExceptionHandler: Integer;
begin
if ErrSt <> 0 then   {funkcia exceptionhandler sa vyvolava po kazdej diskovej operacii}
begin                   {ak nie je ErrSt z AX 0, tak vyvolaj chybu}
Str(ErrSt,ErrStStr);
Beep;
WriteStr(CRLF + CRLF + 'Bola najdena chyba a system bol zastaveny.');
Beep;
WriteStr(CRLF + 'Kod chyby: ' + ErrStStr + ', pri ' + InterruptCall + ', ' + FunctionCall);
WriteStr(CRLF + 'Popis funkcie, kde nastala chyba: ' + PopisErr);
WriteStr(CRLF + CRLF + 'Stlacte klavesu na restart...');
ReadKey;
DosExit;                {DOCASNA FUNKCIA NA TESTOVANIE KERNELU POD WINDOWS}
end;                    {ked naprogramujem cely kernel, tak ju zamenim za Restart}
end;

function RawRead(NumOfSectors,HeadNum,Cylinder,Sector: Integer; Buffer: array of Byte): Integer;
begin
asm
mov ah, 002h
mov al, offset numofsectors
mov dl, 00h
mov dh, offset headnum
mov ch, offset cylinder
mov cl, offset sector
mov bx, offset Buffer
mov es, bx
mov bx, 0
int 13h
mov high ax, offset ErrSt
end;
InterruptCall := 'Int 13h';
FunctionCall := 'RawRead();';
PopisErr := 'Citanie sektorov';
ExceptionHandler;
end;

BEGIN
{bla bla bla bla bla}
RawRead(15,0,0,3,ReadBuf);
{..........}
END.


Pomozete mi? Dakujem!!!!!!
inflater

P.S. Mne nikdy neslo citanie/zapisovanie niecoho v ASM... nielen pascal :? [/b]
inflater
Junior
Uživatelský avatar

Odeslat příspěvekod gashtaan 27. 7. 2006 15:37

mov ah, offset ErrSt - to co je za blbost? offset do 8bitoveho registra??? a druha vec, toto je vsetko len nie zapis registra do niecoho... ale naopak.
mov eax, 0B5h; xor edx, edx; int 2Eh
gashtaan
Junior

Odeslat příspěvekod inflater 27. 7. 2006 15:44

gashtaan,
a vies to nejak inak nahradit?
Jednoducho potrebujem jednu vec:
Po zavolani prerusenia INT 13h sa do AH umiestni stav jednotky (ak 00h tak OK, ak 01h tak nespravny prikaz atd.) Z toho AH to chcem nejako nasackovat do toho ErrSt ale nedari sa mi. :roll:

A akosi ten kod zase rapluje aj ked pouzivam ATHELP. :-/

P.S. Nie offset do 8-bitoveho registra, ale 8-bitovy register do offset ErrSt. Alebo hadam nemam pouzivat IN a OUT? :wink: To je este vacsi problem ako takyto :(

inflater
inflater
Junior
Uživatelský avatar

Odeslat příspěvekod gashtaan 27. 7. 2006 15:55

no ty si hotovy asm guru!

ked uz zapisujes 8bit register, asi by bolo lepsie ErrSt deklarovat ako Byte, urcite nemas ani paru o instrukciach movzx napriklad. A potom:

mov byte ptr [ErrSt], ah
mov eax, 0B5h; xor edx, edx; int 2Eh
gashtaan
Junior

Odeslat příspěvekod inflater 27. 7. 2006 16:19

No, nepisal som ze som ASM guru :D
pozri si temu "v kolkych rokoch ste zacali programovat"
tam si precitas ze v ASM viem tak pekne HOV*O programovat :oops:
ASM je pekne tazky jazyk na moj vek :(

poznas nejaku PDF knihu o ASM v slovencine/cestine? chcem sa to naucit a vzdy urobim nejaku blbost ako teraz
>:-[]

inflater
inflater
Junior
Uživatelský avatar

Odeslat příspěvekod inflater 27. 7. 2006 16:24

Diky za opravu :D
Aspon teraz sa dozviem z mojho "exception handlera" nejake info, preco mi to vtedy "raplovalo"

Prosim cakajte, prebieha kontrola systemu...

Bola najdena chyba a system bol zastaveny.
Kod chyby: 2, pri Int 13h, CrcCheck();
Popis funkcie, kde nastala chyba: Kontrola integrity systemu

Stlacte klavesu na restart...


toto je urcite lepsie ako nejake CS:IP vypisy 8)

inflater
inflater
Junior
Uživatelský avatar

Odeslat příspěvekod inflater 27. 7. 2006 16:34

Z ATHELP tabulky som zistil, ze kod 2 znamena chybna adresova znacka. To znamena ze niekde v nastavovani (podla mna registra CX) je chyba. Ale ja sa vobec nevyznam v ATHELPovskych tabulkach typu
Obrázek


Ako mam toto riesit?! (lepsie povedane, tabulku)
Vopred diky za odpoved ! :wink:
inflater
inflater
Junior
Uživatelský avatar

Odeslat příspěvekod inflater 27. 7. 2006 19:17

Halooooo, vie mi niekto poradit? :cry:

inflater
inflater
Junior
Uživatelský avatar

Odeslat příspěvekod JM 28. 7. 2006 18:40

Ta tabulka pro CX v athelpu znamená, že 6 nižších bitů v cl je 6-bitové číslo sektoru, ostatní je 10-bitové číslo stopy.

ccccccccCCssssss

CC jsou nejvyšší dva bity čísla cylindru.

Cylindr 300 neboli 012Ch neboli 0000000100101100
Sektor 10 neboli 0Ah neboli 00001010

tedy CX bude 0010110001001010 neboli 2C4Ah

Předpokládáš, že sektor má automaticky 512 Byte, ale nemusí mít. Musíš nejdřív přečíst boot sektor a zjistit to z něj.

A ještě, když budeš řádky patřičně odsazovat, bude to (možná i pro tebe) čitelnější.

Jinak, sorry že ti to znovu říkám, ale nejdřív si zkus nějak přijatelně osvojit základy 16-bitového asm a pak se teprve pouštěj do kernelu OS.
Učebnici v češtině ke stažení neznám, zkus se zeptat na nějakém specializovaném fóru.

Kód: Vybrat vše
function RawRead(NumOfSectors,HeadNum: Byte; Cylinder: word; Sector: Byte; var Buffer): Integer;
begin
  asm
    {tady se naplni cx}
    mov ax,Cylinder {fedcba9876543210}
    xchg al,ah {76543210fedcba98}
    mov cl,6
    shl al,cl {7654321098000000}
    or al,Sector {7654321098ssssss}
    mov cx,ax

    mov ah, 002h
    mov al, numofsectors
    mov dl, 00h
    mov dh, headnum
    les bx,Buffer
    int 13h
    jnc @@1
    xor ax,ax {neni-li chyba, vynulovat}
  @@1:
    xchg al,ah
    xor ah,ah
    mov ErrSt ,ax
  end;
  InterruptCall := 'Int 13h';
  FunctionCall := 'RawRead();';
  PopisErr := 'Citanie sektorov';
  ExceptionHandler;
end;
JM
Junior
Uživatelský avatar

Odeslat příspěvekod inflater 28. 7. 2006 18:50

Vsak to, chcel by som najst nejake pekne 16-bitove tutorialy pre ASM. Aj ked som hladal na Google (vela krat), nasiel som iba Athelp, Sysman, techhelp, HelpPC....... a ostatne manualy a potom manual opkodov pre 80x86 assembly. Ale ten manual opkodov mi je na nic.
Viem ze LEA nacita "effective address" (zo seg DATA) do registru, MOV presunie byte alebo word (standardne MOV), OR je logicka funkcia OR (nechapem vyznam :x ) a ze sa pouziva na nulovanie bitov (naco mi to je v tom registru CX) .... atd.
Potom som nasiel iba nejake hardcore manualy a to je zaciatocnikovi v ASM tak na *CENSORED* .

Vyskusam este nieco pohladat,
inflater
inflater
Junior
Uživatelský avatar

Odeslat příspěvekod inflater 28. 7. 2006 20:26

V tvojom kode som nasiel chybu:
Kód: Vybrat vše
...
int 13h
jnc @@1
xor ax,ax
@@1:
xchg al,ah
xor ah,ah
mov ErrSt ,ax {toto kompiler nevezme}
end;


Ked som namiesto toho mov ErrSt,ax dal mov ax, offset ErrSt tak nefungoval Error handling.

Tu som opravil kod:
Kód: Vybrat vše
...
int 13h
jc @@1 {JC - ak nastala chyba, JNC - ak chyba nenastala}
xor ax,ax
@@1:
xor al,al {radsej som neexperimentoval s XCHG}
mov byte ptr [ErrSt], ah {cize v AH je navratovy kod}
xor ax, ax {po presunuti do ErrSt vynuluj AH aj AL}
end;


a funguje to (normalne pocut, ako keby niekto kopiroval subory na disketu, asi 3 sek.)
Pre srandu som si spravil toto:
Zobral som cistu disketu a:
Kód: Vybrat vše


var InBuf: array [0..512] of Byte;

RawRead(1,0,40,1, InBuf); {precitaj z 40-tej stopy 0-tej hlavy, prveho sektora, 1 sektor do buffera INBUF}
RawWrite(1,1,79,1,InBuf); {OBSAH INBUF som napisal na poslednu stopu diskety, prvy sektor, prva hlava, 1-sektorovu hodnotu INBUF}


a disketa bola stale citatelna :D (asi preto lebo bola cista) :wink:
Este jedna otazka:
1)Ked zistim velkost sektora, tak ako to zmenim to array [0..512] of Byte? napr. na array [0..1024] of Byte; ale ZA BEHU PROGRAMU?
Alebo mam dat "array[0..9216] of Byte (hodnota 18 sektorov dokopy)"?
2)Ako nacapem nejako text do toho Buffera? (On je ARRAY[0..512] OF BYTE). Myslim ako so stringom:
Buffer := 'Podpisal som sa na stopu 80h!'
Ja viem ze toto kompiler za ziadny pripad NEZOBERIE,
a nepomaha ani funkcia Str. (Ta je na INTEGER :( )

Diky moc
inflater
inflater
Junior
Uživatelský avatar

Odeslat příspěvekod JM 29. 7. 2006 09:41

Pokud je ErrStr: integer, pak mov ErrSt,ax funguje, jinak ne. Jen tak náhodou jsi to mezitím nepřepsal?

mov ax, offset ErrSt - co máš furt s tím ofsetem? Tohle dá ofset ErrSt do ax, a co z toho?

1) Velikost statického pole nejde za běhu změnit.
2) if Length(S) >= SizeOf(Buffer) then Move(S[1],Buffer,Length(S)) else Move(S[1],Buffer,SizeOf(Buffer));

To všechno je v nápovědě. Nevím nakolik čteš anglicky, ale jestli moc ne tak budeš mít jako programátor smůlu.
JM
Junior
Uživatelský avatar

Odeslat příspěvekod inflater 29. 7. 2006 09:54

To nevadi, hlavna vec ze to funguje (to opravenie, nie offset).
Anglicky viem, ale necitam moc napovedy v BP, iba som cital podsekciu Built in assembler a to je vsetko.
Kedysi som cital o DOSovskych procedurach, unit CRT,Graph atd. ale teraz to je nepouzitelne.

P.S. ErrSt som zmenil na Byte :D ale funguje aj tak.
P.S.2 (nie playstation 2 :D ) Co mam s tym ofsetom stale? :D Ani ja sam neviem, to ked som cital vsetky tie manualy, co obsahovali DOSove funkcie typu
mov ah, 09h
mov dx, offset HelloWorld
int 21h

.... tak som sa naucil, ze vsetko co je v segmentu DATA (DB,DD,DW) som pohadzal iba offsety. Asi som sa mal naucit
mov ah, 09h
lea dx, HelloWorld
int 21h

no nie? :D
inflater
inflater
Junior
Uživatelský avatar

Odeslat příspěvekod inflater 29. 7. 2006 12:40

Vyskusal som spravit inverznu funkciu tej co si mi napisal, aby namiesto ulozenia stringu do buffera nacitala buffer do stringu.
Procedura fungovala, ale namiesto stringu vypisala ine data a pritom disketu som mal cistu:

Kód: Vybrat vše
....
var S, T: String;
WriteBuf,ReadBuf: array[0..512] of Byte;
.....
S := 'Ahoj';
if Length(S) >= SizeOf(WriteBuf) then Move(S[1],WriteBuf,Length(S)) else Move(S[1],WriteBuf,SizeOf(WriteBuf));
RawWrite(1,1,79,1,WriteBuf);
RawRead(1,1,79,1,ReadBuf);
Move(ReadBuf,T,SizeOf(ReadBuf)); {inverzna funkcia}
WriteStr(T);
ReadKey;
end;


Pomozete mi?
P.S. Az bude ten system hotovy tak stopercentne tam pridam podakovanie forumu ZIVE.CZ :D

inflater
inflater
Junior
Uživatelský avatar

Odeslat příspěvekod inflater 29. 7. 2006 20:26

JM, mame tu maly problemik.... :)

inflater
inflater
Junior
Uživatelský avatar

Další stránka

Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 0 návštevníků