Searching for string problems
Hello!
OK. I've solved my problems with storing data (problem was with improper DS setup - thanks to all, pointed me to this). And now I should perform a search in the BIOS are for particular string (version of BIOS ). Here is my code (it's located in the setup.S, so executes in the real mode, not ptotected).
-->start_of_setup:
jmp cl_startcl_id_str: .string "BIOS 0.1"cl_start:
movb $0, %al
movw $0xe000, %bx
cl_compare:
incw %bx
movw %bx, %si
cmpw $0xefff, %si
je cl_compare_done
movw $cl_id_str, %di
cl_compare_inner:
movb (%di), %ah
cmpb $0, %ah
je cl_compare_done_good
cmpb (%si), %ah
jne cl_compare
incw %si
incw %di
jmp cl_compare_inner
cl_compare_done_good:
movb $1, %alcl_compare_done:
<--
This code don't work... I'm sure, that's because of inproper registers setup (or maybe address range is wrong). Please help me.
Best regards,
Andrew.
Quoted 31 lines · Andrew Kirilenko
Hello!
OK. I've solved my problems with storing data (problem was with improper DS setup - thanks to all, pointed me to this). And now I should perform a search in the BIOS are for particular string (version of BIOS ). Here is my code (it's located in the
setup.S, so executes in the real mode, not ptotected).-->
start_of_setup:
jmpcl_startcl_id_str: .string "BIOS 0.1"cl_start:movb $0, %al movw $0xe000, %bx cl_compare: incw %bx movw %bx, %si cmpw $0xefff, %si je cl_compare_done movw $cl_id_str, %di cl_compare_inner: movb (%di), %ah cmpb $0, %ah je cl_compare_done_good cmpb (%si), %ah jne cl_compare incw %si incw %di jmp cl_compare_inner cl_compare_done_good: movb $1, %al
Quoted 6 lines
cl_compare_done:
<--This code don't work... I'm sure, that's because of inproper registers setup (or maybe address range is wrong). Please help me.
Hmm, maybe you should just learn assembly off-line.
cl_id_str: .string "BIOS 0.1"cl_id_end:
scan: movw %cs, %ax # Get code-segment
movw %ax, %ds # Set into data segment
movw %ax, %es # Set into extra segment CS=ES=DS
cld # Compare forwards
movw $cl_id_str, %si # String to compare
movw $were_in_the_bios_you_expect_to_find_it, %di
movw $cl_id_end, %cx # Offset to this label
subw %si, %cx # CX = length of string
decw %cx # Don't compare \0
repz cmpsb # Continue as long as they compare
jz found # String was found
# Not found here
found:
If you need to search the whole BIOS for that string, you need to set up an outer loop using an unused register which starts at the offset of the BIOS and increments by one byte everytime you can't find the string. This value gets put into %di, instead of the absolute number specified above.
Like:
scan: movw %cs, %ax
movw %ax, %ds movw %ax, %es movw $where_in_BIOS_to_start, %bx cld
1: movw $cl_id_str, %si # Offset of search string
movw $cl_id_end, %cx # Offset of string end + 1
subw %si, %cx # String length
decw %cx # Don't look for the \0
movw %bx, %di # ES:DI = where to look
repz cmpsb # Loop while the same
jz found # Found the string
incb %bx # Next starting offset
cmpb $_BIOS_END, %bx # Check for limit
jb 1b # Continuenever_found_anywhere:
found:
Note that the gas .string macro puts in a '\0', assuming it's a 'C' string. You don't want to put that in the comparison. That's why you search one-less than the allocation length. There are predefined macros available for 'len', also.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips). Why is the government concerned about the lunatic fringe? Think about it.
Hello!
Quoted 25 lines
If you need to search the whole BIOS for that string, you need to set up an outer loop using an unused register which starts at the offset of the BIOS and increments by one byte everytime you can't find the string. This value gets put into %di, instead of the absolute number specified above.
Like:
scan: movw %cs, %ax
movw %ax, %ds movw %ax, %es movw $where_in_BIOS_to_start, %bx cld1: movw $cl_id_str, %si # Offset of search string
movw $cl_id_end, %cx # Offset of string end + 1
subw %si, %cx # String length
decw %cx # Don't look for the \0
movw %bx, %di # ES:DI = where to look
repz cmpsb # Loop while the same
jz found # Found the string
incb %bx # Next starting offset
cmpb $_BIOS_END, %bx # Check for limit
jb 1b # Continuenever_found_anywhere:
Quoted 1 line
found:
I've written something similar to this before - and it wont' work, so I've reimplemented it. The problem is, that I don't know how to set ES properly. I only know, that BIOS data (and code) is located in 0xe000..0xf000 (real address).
Best regards,
Andrew.
Quoted 27 lines · Andrew Kirilenko
Hello!
Quoted 25 lines
If you need to search the whole BIOS for that string, you need to set up an outer loop using an unused register which starts at the offset of the BIOS and increments by one byte everytime you can't find the string. This value gets put into %di, instead of the absolute number specified above.
Like:
scan: movw %cs, %ax
movw %ax, %ds movw %ax, %es movw $where_in_BIOS_to_start, %bx cld1: movw $cl_id_str, %si # Offset of search string
movw $cl_id_end, %cx # Offset of string end + 1
subw %si, %cx # String length
decw %cx # Don't look for the \0
movw %bx, %di # ES:DI = where to look
repz cmpsb # Loop while the same
jz found # Found the string
incb %bx # Next starting offset
cmpb $_BIOS_END, %bx # Check for limit
jb 1b # Continuenever_found_anywhere:
Quoted 7 lines
Quoted 1 line
found:
I've written something similar to this before - and it wont' work, so I've reimplemented it. The problem is, that I don't know how to set ES properly. I only know, that BIOS data (and code) is located in 0xe000..0xf000 (real address).
Yeah. So. I set ES and DS to be exactly where CS is. This means that if your &!)(^$&_ code executes it will work. So, instead of trying it, you just blindly ignore it and state that it won't work.
Bullshit. I do this for a living and I gave you some valuable time which you rejected out-of-hand. Have fun.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips). Why is the government concerned about the lunatic fringe? Think about it.
Hello!
Quoted 24 lines
Quoted 17 lines
Quoted 17 lines
scan: movw %cs, %ax
movw %ax, %ds movw %ax, %es movw $where_in_BIOS_to_start, %bx cld1: movw $cl_id_str, %si # Offset of search string
movw $cl_id_end, %cx # Offset of string end + 1
subw %si, %cx # String length
decw %cx # Don't look for the \0
movw %bx, %di # ES:DI = where to look
repz cmpsb # Loop while the same
jz found # Found the string
incb %bx # Next starting offset
cmpb $_BIOS_END, %bx # Check for limit
jb 1b # Continuenever_found_anywhere:Quoted 6 lines
Quoted 1 line
found:
I've written something similar to this before - and it wont' work, so I've reimplemented it. The problem is, that I don't know how to set ES properly. I only know, that BIOS data (and code) is located in 0xe000..0xf000 (real address).
Quoted 6 lines
Yeah. So. I set ES and DS to be exactly where CS is. This means that if your &!)(^$&_ code executes it will work. So, instead of trying it, you just blindly ignore it and state that it won't work.
Bullshit. I do this for a living and I gave you some valuable time which you rejected out-of-hand. Have fun.
Of course, I've tried your code as well - the same result! Sorry, if you haven't understand me.
The problem is, that I don't know where this BIOS code is relative to current code segment (CS). I only know (hope), that it should be in 0x0:0xe000...0x0:0xf000. I have tried to set ES to 0 (xor %ax, %ax; mov %ax, %es) - no luck as well. BTW, strings /dev/mem | grep "REQUESTED STRING" founds it perfectly...
Best regards,
Andrew.
Quoted 42 lines · Andrew Kirilenko
Hello!
Quoted 24 lines
Quoted 17 lines
Quoted 17 lines
scan: movw %cs, %ax
movw %ax, %ds movw %ax, %es movw $where_in_BIOS_to_start, %bx cld1: movw $cl_id_str, %si # Offset of search string
movw $cl_id_end, %cx # Offset of string end + 1
subw %si, %cx # String length
decw %cx # Don't look for the \0
movw %bx, %di # ES:DI = where to look
repz cmpsb # Loop while the same
jz found # Found the string
incw %bx # Next starting offset
cmpw $_BIOS_END, %bx # Check for limit
jb 1b # Continuenever_found_anywhere:Quoted 6 lines
Quoted 1 line
found:
I've written something similar to this before - and it wont' work, so I've reimplemented it. The problem is, that I don't know how to set ES properly. I only know, that BIOS data (and code) is located in 0xe000..0xf000 (real address).
Quoted 6 lines
Yeah. So. I set ES and DS to be exactly where CS is. This means that if your &!)(^$&_ code executes it will work. So, instead of trying it, you just blindly ignore it and state that it won't work.
Bullshit. I do this for a living and I gave you some valuable time which you rejected out-of-hand. Have fun.
Of course, I've tried your code as well - the same result! Sorry, if you haven't understand me.
The problem is, that I don't know where this BIOS code is relative to current code segment (CS). I only know (hope), that it should be in 0x0:0xe000...0x0:0xf000. I have tried to set ES to 0 (xor %ax, %ax; mov %ax, %es) - no luck as well. BTW,
strings /dev/mem | grep "REQUESTED STRING"founds it perfectly...
Quoted 3 lines
Best regards,
Andrew.
-
The bios is in segment 0xf000. You set ES to that area. ES:DI will start at 0 if bx=0 in the code shown. The BIOS is only 64k. This means that where bx is being incremented (it should be incw, not incb). It would generate an assembly error with incb which is why I knew you didn't even try it. -- you just jnz back to 1b, without any additional test.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips). Why is the government concerned about the lunatic fringe? Think about it.
Hello!
Quoted 25 lines
Quoted 21 lines
Quoted 11 lines
Quoted 4 lines
I've written something similar to this before - and it wont' work, so I've reimplemented it. The problem is, that I don't know how to set ES properly. I only know, that BIOS data (and code) is located in 0xe000..0xf000 (real address).
Yeah. So. I set ES and DS to be exactly where CS is. This means that if your &!)(^$&_ code executes it will work. So, instead of trying it, you just blindly ignore it and state that it won't work.
Bullshit. I do this for a living and I gave you some valuable time which you rejected out-of-hand. Have fun.
Of course, I've tried your code as well - the same result! Sorry, if you haven't understand me.
The problem is, that I don't know where this BIOS code is relative to current code segment (CS). I only know (hope), that it should be in 0x0:0xe000...0x0:0xf000. I have tried to set ES to 0 (xor %ax, %ax; mov %ax, %es) - no luck as well. BTW,
strings /dev/mem | grep "REQUESTED STRING"founds it perfectly...Quoted 3 lines
Best regards,
Andrew.
-
Quoted 6 lines
The bios is in segment
0xf000. You set ES to that area. ES:DI will start at 0 if bx=0 in the code shown. The BIOS is only 64k. This means that where bx is being incremented (it should be incw, not incb). It would generate an assembly error with incb which is why I knew you didn't even try it. -- you just jnz back to 1b, without any additional test.
1. How to set ES to this area? "movw $0xf000, %ax ; movw %ax, %es" will be enough?
2. Is the are really starts from 0xf000? Or 0xe000?
3. I'm smart enough to correct "incb %bx" to "incw %bx" ;)
Best regards,
Andrew.
On Wed, 23 Apr 2003 22:00:20 +0300 Andrew Kirilenko <[email protected]> wrote:
| Hello! | | > > > > I've written something similar to this before - and it wont' work, so | > > > > I've reimplemented it. The problem is, that I don't know how to set | > > > > ES properly. I only know, that BIOS data (and code) is located in | > > > > 0xe000..0xf000 (real address). | > > > | > > > Yeah. So. I set ES and DS to be exactly where CS is. This means that | > > > if your &!)(^$&_ code executes it will work. So, instead of trying | > > > it, you just blindly ignore it and state that it won't work. | > > > | > > > Bullshit. I do this for a living and I gave you some valuable time | > > > which you rejected out-of-hand. Have fun. | > > | > > Of course, I've tried your code as well - the same result! Sorry, if you | > > haven't understand me. | > > | > > The problem is, that I don't know where this BIOS code is relative to | > > current code segment (CS). I only know (hope), that it should be in | > > 0x0:0xe000...0x0:0xf000. I have tried to set ES to 0 (xor %ax, %ax; mov | > > %ax, %es) - no luck as well. BTW, `strings /dev/mem | grep "REQUESTED | > > STRING"` founds it perfectly... | > > | > > Best regards, | > > Andrew. | > > - | > | > The bios is in segment 0xf000. You set ES to that area. ES:DI will | > start at 0 if bx=0 in the code shown. The BIOS is only 64k. | > This means that where bx is being incremented (it should be incw, not | > incb). It would generate an assembly error with incb which is why | > I knew you didn't even try it. -- you just jnz back to 1b, without | > any additional test. | | 1. How to set ES to this area? "movw $0xf000, %ax ; movw %ax, %es" will be | enough?
That should do it.
| 2. Is the are really starts from 0xf000? Or 0xe000?
Most current ones that I know of are 128 KB, so start at segment 0xe000:0 thru 0xf000:ffff.
Just boot DOS, run debug, and display those areas. That will answer it for you. :)
| 3. I'm smart enough to correct "incb %bx" to "incw %bx" ;)
--
~Randy
Quoted 34 lines · Andrew Kirilenko
Hello!
Quoted 25 lines
Quoted 21 lines
Quoted 11 lines
Quoted 4 lines
I've written something similar to this before - and it wont' work, so I've reimplemented it. The problem is, that I don't know how to set ES properly. I only know, that BIOS data (and code) is located in 0xe000..0xf000 (real address).
Yeah. So. I set ES and DS to be exactly where CS is. This means that if your &!)(^$&_ code executes it will work. So, instead of trying it, you just blindly ignore it and state that it won't work.
Bullshit. I do this for a living and I gave you some valuable time which you rejected out-of-hand. Have fun.
Of course, I've tried your code as well - the same result! Sorry, if you haven't understand me.
The problem is, that I don't know where this BIOS code is relative to current code segment (CS). I only know (hope), that it should be in 0x0:0xe000...0x0:0xf000. I have tried to set ES to 0 (xor %ax, %ax; mov %ax, %es) - no luck as well. BTW,
strings /dev/mem | grep "REQUESTED STRING"founds it perfectly...Quoted 3 lines
Best regards,
Andrew.
-Quoted 6 lines
The bios is in segment
0xf000. You set ES to that area. ES:DI will start at 0 if bx=0 in the code shown. The BIOS is only 64k. This means that where bx is being incremented (it should be incw, not incb). It would generate an assembly error with incb which is why I knew you didn't even try it. -- you just jnz back to 1b, without any additional test.
Quoted 2 lines
1. How to set ES to this area? "movw $0xf000, %ax ; movw %ax, %es" will be enough?
Yes.
Quoted 1 line
2. Is the are really starts from
0xf000? Or0xe000?
The stuff used to boot, usually the relocated and shadowed BIOS ROM, always exists at absolute address 0x000f0000. Since a 'segment' is a 16-byte thing, the appropriate segment is 0xf000. The code must be there because the 'reset-vector' is (must be) 16 bytes from the end of this segment. That's the code that first gets control during the startup sequence.
The BIOS setup menus and other stuff is (typically) put down at 0xe000. However many new BIOS uncompress some stuff from NVRAM and put it anywhere they want because they 'own' all the RAM in the system until an attempted boot.
Quoted 4 lines
3. I'm smart enough to correct "incb %bx" to "incw %bx" ;)
Best regards,
Andrew.
If you use the string search primative I show, it will work.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips). Why is the government concerned about the lunatic fringe? Think about it.
Hello!
Big thanks to all of you. Now I'm starting to understand how it's working. Here is current version of my code:
-->
jmp cl_startcl_id_str: .string "STRING"cl_start:
cld
movw %cs, %ax
movw %ax, %ds
movw $0xe000, %ax
movw %ax, %es
movb $0, %al
xor %bx, %bx # start of segmentcl_compare:
movw $cl_id_str, %si
movw $cl_start, %cx
subw %si, %cx
decw %cx
movw %bx, %di
repz cmpsb
je cl_compare_done_good
incw %bx
cmpw $0xffff, %bx # are we at the end of segment
je cl_compare_done
jmp cl_compare
cl_compare_done_good:
movb $1, %alcl_compare_done:
<--
And this code won't work as well :(
Unfortunately, I can't start DOS and check, cause there is no video and keyboard controller on that PC.
Best reagrds,
Andrew.
Quoted 33 lines · Andrew Kirilenko
Hello!
Big thanks to all of you. Now I'm starting to understand how it's working. Here is current version of my code:
-->
jmpcl_startcl_id_str: .string "STRING"cl_start:
cld
movw %cs, %ax
movw %ax, %ds
movw $0xe000, %ax
movw %ax, %es
movb $0, %al
xor %bx, %bx # start of segmentcl_compare:movw $cl_id_str, %si movw $cl_start, %cx subw %si, %cx decw %cx movw %bx, %di repz cmpsb je cl_compare_done_good incw %bx cmpw $0xffff, %bx # are we at the end of segment je cl_compare_done jmp cl_compare cl_compare_done_good: movb $1, %al
cl_compare_done:
<--
Quoted 7 lines
And this code won't work as well :(
Unfortunately, I can't start DOS and check, cause there is no video and keyboard controller on that PC.
Best reagrds,
Andrew.
Change this:
movw $0xe000, %ax
To:
movw $0xf000, %ax
... like I told you. The BIOS ROM contents, the stuff that has the serial number _must_ start where I told you.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips). Why is the government concerned about the lunatic fringe? Think about it.
Hello!
Quoted 9 lines
Quoted 6 lines
And this code won't work as well :(
Unfortunately, I can't start DOS and check, cause there is no video and keyboard controller on that PC.
Change this:
Quoted 7 lines
movw $0xe000, %axTo:
movw $0xf000, %ax... like I told you. The BIOS ROM contents, the stuff that has the serial number _must_ start where I told you.
Already solved the problem. AX was overwritten, before storing it's value (0 or 1) into memory. The most stupid mistake, I've seen last year. 20 hours of kernel programming without breaks isn't really good.
Thanks too all of you, once again. You really saved my life.
Best regards,
Andrew.
On Wed, 23 Apr 2003 22:48:35 +0300 Andrew Kirilenko <[email protected]> wrote:
| Hello! | | Big thanks to all of you. Now I'm starting to understand how it's working. | Here is current version of my code: | | --> | jmp cl_start | cl_id_str: .string "STRING" | cl_start: | cld | movw %cs, %ax | movw %ax, %ds | movw $0xe000, %ax | movw %ax, %es | movb $0, %al | xor %bx, %bx # start of segment | cl_compare: | movw $cl_id_str, %si | movw $cl_start, %cx | subw %si, %cx | decw %cx | movw %bx, %di | repz cmpsb | je cl_compare_done_good | incw %bx | cmpw $0xffff, %bx # are we at the end of segment | je cl_compare_done | jmp cl_compare | cl_compare_done_good: | movb $1, %al | cl_compare_done:
# here the code needs to do something like this, # to check the second 64 KB block of memory: movw %es, %bx cmpw %bx, $0xe000 je all_done movw $0xf000, %bx movw %bx, %es xor %bx, %bx jmp cl_compare
| <-- | | And this code won't work as well :(
Do you understand x86 real-mode segment registers? They can only address a "segment" of 64 KB (roughly).
| Unfortunately, I can't start DOS and check, cause there is no video and | keyboard controller on that PC.
oh yes.
--
~Randy
On Wed, 23 Apr 2003 21:25:22 +0300 Andrew Kirilenko <[email protected]> wrote:
| Hello! | | > > > scan: movw %cs, %ax | > > > movw %ax, %ds | > > > movw %ax, %es | > > > movw $where_in_BIOS_to_start, %bx | > > > cld | > > > 1: movw $cl_id_str, %si # Offset of search string | > > > movw $cl_id_end, %cx # Offset of string end + 1 | > > > subw %si, %cx # String length | > > > decw %cx # Don't look for the \0 | > > > movw %bx, %di # ES:DI = where to look | > > > repz cmpsb # Loop while the same | > > > jz found # Found the string | > > > incb %bx # Next starting offset | > > > cmpb $_BIOS_END, %bx # Check for limit | > > > jb 1b # Continue | > > > never_found_anywhere: | > > > | > > > found: | > > | > > I've written something similar to this before - and it wont' work, so | > > I've reimplemented it. The problem is, that I don't know how to set ES | > > properly. I only know, that BIOS data (and code) is located in | > > 0xe000..0xf000 (real address). | > | > Yeah. So. I set ES and DS to be exactly where CS is. This means that | > if your &!)(^$&_ code executes it will work. So, instead of trying | > it, you just blindly ignore it and state that it won't work. | > | > Bullshit. I do this for a living and I gave you some valuable time | > which you rejected out-of-hand. Have fun. | | Of course, I've tried your code as well - the same result! Sorry, if you | haven't understand me. | | The problem is, that I don't know where this BIOS code is relative to current | code segment (CS). I only know (hope), that it should be in | 0x0:0xe000...0x0:0xf000. I have tried to set ES to 0 (xor %ax, %ax; mov %ax, | %es) - no luck as well. BTW, `strings /dev/mem | grep "REQUESTED STRING"` | founds it perfectly...
You shouldn't need to know where the BIOS code is "relative to current code segment." It "should be" in hex 0:e000-ffff. You should be able to use some segment reg. = 0 to search.
I see that Dick just corrected this, just as I was about to do:
Typical PC BIOSen are at segment 0xe000:0 thru 0xf000:ffff, not segment 0 and offsets as you have them listed. Are you using a typical PC BIOS or something else?
--
~Randy