flat assembler
Message board for the users of flat assembler.
Index
> DOS > Checking for PCI BIOS |
Author |
|
LocoDelAssembly 17 Jan 2013, 18:03
Change ' ICP' to 'PCI ' (fasm already reverses the string for you), and replace 24h with 24h, 0dh, 0ah (just in case FreeDOS is having some sort of line buffering which is preventing your prints to be shown). "call error" should probably be "jmp error" (but shouldn't be the reason for the failure)
|
|||
17 Jan 2013, 18:03 |
|
shutdownall 17 Jan 2013, 18:50
Cyril wrote: Hello, I'm only starting to learn assembly and have a great desire to learn . I've written a program that checks if a computer has PCI BIOS installed. Here's the code: First look here http://www.ctyme.com/intr/rb-2371.htm and here http://www.ctyme.com/rbrown.htm for more information about DOS/BIOS interrupts, what they need and what they give back. And the string 'PCI' is delivered back in edx and not edi. You may compare to the following value instead of using strings if you are not familar with them: EDX = 20494350h (' ICP') |
|||
17 Jan 2013, 18:50 |
|
freecrac 18 Jan 2013, 08:45
use32 is not a good choice for 16 bit software interrupts.
And "use32" is only highly recommended if we use the 32 bit mode and the "D"-Flag is already set before. The only one difference between the 16 bit mode and the 32 bit mode is the consideration and meaning of the adresssize- and the operandsize prefix and how our cpu is interpreting an opcode with or without those prefixes. Quote:
Dirk |
|||
18 Jan 2013, 08:45 |
|
Cyril 18 Jan 2013, 10:42
Thanks for the quick response. Yes, my bad, it was EDX, not EDI.
Well, I've made some changes - but still nothing. Code: use32 org 100h mov eax, 0000B101h ; check for PCI BIOS presence sub edi, edi ; why? int 1Ah ; time of the day AND PCI functions? cmp edx, 'PCI ' ; EDX has ' ICP'; FASM reverses it back je next ; success -> proceed stc ; set carry flag to 1 (=error) jmp error ; error handling next: mov ah, 9 mov dx, successmsg ; print success message int 21h int 20h error: mov ah, 9 mov dx, errormsg ; print error message int 21h int 20h successmsg db 'PCI BIOS found!', 24h, 0Dh, 0Ah errormsg db 'PCI BIOS not found!', 24h, 0Dh, 0Ah In fact, I'm not really sure it's because of the "use32" directive. Otherwise it would say something like "wrong opcode". But who knows? Could you also explain what means "FASM reverses the string", from ICP back to PCI? When does that happen and why? No matter if I write ' ICP' or 'PCI ' in the listing, the result is total zero. And also what's the difference between "call error" and "jump error"? I heard "call" changes some flags. (How) does it matter? 2freecrac: thanks a lot for the quote, but that's too much for me to grasp for now... |
|||
18 Jan 2013, 10:42 |
|
Picnic 18 Jan 2013, 12:45
Cyril wrote:
Hi, See fasm's FAQ, third question. |
|||
18 Jan 2013, 12:45 |
|
JohnFound 18 Jan 2013, 13:39
Remove this "use32".
|
|||
18 Jan 2013, 13:39 |
|
LocoDelAssembly 18 Jan 2013, 18:13
How could I missed that use32...
Code: org 100h ; INT 1A - PCI BIOS v2.0c+ - INSTALLATION CHECK mov ax, $B101 xor edi, edi int $1A ;Return: ;AH = 00h if installed ;CF clear ;EDX = 20494350h (' ICP') ;EDI = physical address of protected-mode entry point (see #00731) ;AL = PCI hardware characteristics (see #00730) ;BH = PCI interface level major version (BCD) ;BL = PCI interface level minor version (BCD) ;CL = number of last PCI bus in system ;EAX, EBX, ECX, and EDX may be modified ;all other flags (except IF) may be modified jc error cmp ah, 0 jne error cmp edx, 'PCI ' je error mov dx, successmsg print: mov ah, 9 int 21h int 20h error: mov dx, errormsg jmp print successmsg db 'PCI BIOS found!', 24h errormsg db 'PCI BIOS not found!', 24h And to clarify why use32 must not be used when the processor is running in 16-bit mode, this is the dissassembly produced with DEBUG (with some comments of mine): Code: B801B1 MOV AX,B101 0000 ADD [BX+SI],AL ; This is the highest two bytes of MOV EAX, 0000B101 misinterpreted as an instruction because of the missing operand size override prefix 29FF SUB DI,DI CD1A INT 1A 81FF2049 CMP DI,4920 ; The next two instructions appear because of the same issue. 43 INC BX ; 43h = 'C' 50 PUSH AX ; 50h = 'P' 7406 JZ 0117 F9 STC E80A00 CALL 011F 0000 ADD [BX+SI],AL ; Same problem again B409 MOV AH,09 66 DB 66 ; Operand size override prefix. The next instruction is MOV EDX, ... actually. BA2B01 MOV DX,012B CD21 INT 21 ; It won't be executed because the processor interpreted "MOV EDX, 21CD012Bh" and the highest two bytes of the operand are precisely this instruction CD20 INT 20 B409 MOV AH,09 66 DB 66 BA3B01 MOV DX,013B CD21 INT 21 ; Won't be executed because of the same reason as before. CD20 INT 20 |
|||
18 Jan 2013, 18:13 |
|
Cyril 19 Jan 2013, 10:54
Thank you VERY much!
So it appears, "use32" was the real problem! In fact, I didn't know that I could use 32-bit registers in 16-bit mode and it would work. As for your corrections. I have a few more questions. I've noticed that if I do only Code: org 100h mov ax, $B101 xor edi, edi int 1Ah ; this is more convenient for me to read jc error mov dx, successmsg print: mov ah, 9 int 21h int 20h error: mov dx, errormsg jmp print successmsg db 'PCI BIOS found!', 24h errormsg db 'PCI BIOS not found!', 24h and remove Code: cmp ah, 0 jne error cmp edx, 'PCI ' je error it works flawlessly. Why do I need to do triple check (jump if carry, AH not 0, 'PCI ' string in EDX) if the carry flag tells about success or error right away? Or is my variant too "dirty"? |
|||
19 Jan 2013, 10:54 |
|
shutdownall 19 Jan 2013, 11:56
You should check if AH is 0.
Please refer to the documentation. Quote:
It says: CF is clear, it does not say CF is cleared when PCI BIOS is installed. I would assume that CF is cleared always as it is not pointed out. So I would check if AH is 0. By the way, this check is more likely done with Code:
or ah,ah
jnz error
This is done faster and better code. The zero flag will be set on "or ah,ah" when ah is zero. jnz = jump if not zero Have fun. PS: I think it would be hard to find a PC without PCI BIOS - so is check is more obsolete today ... |
|||
19 Jan 2013, 11:56 |
|
ACP 19 Jan 2013, 15:38
shutdownall wrote:
I believe DosBox is one that return no PCI BIOS result in case of this call which would be hardly a surprise if you look at BIOS code mapped into memory - its more of a stub than true BIOS. So this might not be as obsolete as it might look like assuming DOS API is not obsolete either. Also if this is supposed to be part of real application than first one must check if 32bit registers are supported by detecting cpu type. The INT 1Ah requires also free space on stack - don't forget about it if you will convert from COM file format to EXE (add appropriate "stack [value]" keyword to the source). |
|||
19 Jan 2013, 15:38 |
|
Cyril 19 Jan 2013, 16:13
shutdownall wrote: PS: I think it would be hard to find a PC without PCI BIOS - so this check is more obsolete today ... In this case it says, "PCI BIOS not found!" We must foresee many things while programming in asm, don't we? And yes, it's supposed to be a part of a bigger application - but it will be in COM format. I'm just starting to learn, I don't want to mess up with EXEs for now. |
|||
19 Jan 2013, 16:13 |
|
LocoDelAssembly 19 Jan 2013, 17:51
Still errors? Can't believe it... After changing JE with JNE it now says not found in both DosBox and WindowsXP, and in the case of WindowsXP under VirtualBox EDI=EDX=0.
Code: AX=0001 BX=0000 CX=0055 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=19A9 ES=19A9 SS=19A9 CS=19A9 IP=0112 NV UP EI PL ZR NA PE NC |
|||
19 Jan 2013, 17:51 |
|
freecrac 19 Jan 2013, 21:20
Cyril wrote: In fact, I didn't know that I could use 32-bit registers in 16-bit mode and it would work. Without those prefixeses we can only use 16 bit operands and 16 bit adresses. (In the 16-bit mode it is also possible to use 64 Bit MMX- and 128 bit SSE- register, if the CPU provide these extensions(testing CPUID instruction).) In the 32 bit mode the basic of those adresssize/operandsize prefixes will l be fundamentally changed. So if we want to use in the 32 bit mode 32 bit register and/or 32 bit operands, then we have to leave off those prefixes from our opcode. But if we want to use in the 32 bit mode 16 bit operands and 16 bit addsesses, then we have to add those prefixes to our opcode. The oprerandsize prefix and the adresssize prefix works diametrically opposite to the 16 bit mode for the real addressmode and for the protected mode. .. So it is also possible with the 16 bit protected mode to use 32 bit address-register for to address the full address-space of the 32 bit area of 4 GB memmory. (With enlarging the default segmentsize from 64 KB in the GDT/LDT segment entries.) Additional we can use all of our ram of 4 GB, if it psysical exist and if it free and not preallocated from the mainboard bios for peripherie components. It is also possible to use the 32 bit mode with the real address mode, but most of the bios routines are build for the 16 bit mode and do not work together with the 32 bit mode and this exacctly is the reason why we have to use the 16 bit mode, if we want to use 16 bit software interrupts. Dirk |
|||
19 Jan 2013, 21:20 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.