Assembly Challenge: Shortest Code
Assembly Challenge: Shortest Code
The goal: Test bit 29 (0x20000000) in EDX in 16-bit real mode, and jump to an address if it is set.
For example:
test edx, 0x20000000
jnz edx_set
But that's too long. I got it down to six bytes, see if you can match that or do better.
Mike
For example:
test edx, 0x20000000
jnz edx_set
But that's too long. I got it down to six bytes, see if you can match that or do better.
Mike
Re: Assembly Challenge: Shortest Code
I wish I'd know x86 assembly opcodes better this sounds like a funny challenge but I will never find out shorter combination because I know too few instructions from x86 instruction set. that one you have there, I guess it's (2 + 1 + 1 + 4) + (1 + 1 + 1), 11 bytes long.
Windows Vista rapes you, cuts you and pisses inside. Thought these are just nifty side-effects.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
I assume you destroyed EDX in the process of getting 6 bytes?
Code: Select all
rol edx, 3 ; prefix opcode modrm immediate (4)
jc target_set ; opcode immediate (2)
; 6 bytes total
7 bytes for nondestructive (bt, jc). Can't find anything short enough to make 6 bytes, esp. in realmode since you pretty much always lose a byte on 0x66. If you can assume that edx either has bit 29 set or doesn't have anything set, you can xor it with zero-extended 0 for an indication... but that's kind of cheating and I still doubt it'll be shorter.Combuster wrote:I assume you destroyed EDX in the process of getting 6 bytes?Code: Select all
rol edx, 3 ; prefix opcode modrm immediate (4) jc target_set ; opcode immediate (2) ; 6 bytes total
The jump will be 2 bytes in any case, the opcode prefix counts for 1, you need an imm of some kind that also takes one byte, you need a modrm to access the register (push/pop/inc/dec don't work and the rest is with modrm or more bytes) and an opcode byte so I think this proves, aside from AMD/Intel sidestepping us by making an instruction with this specific function, that it's not possible to shorten this below 6 bytes for destructive. Below 7 for nondestructive anybody?
I destroyed EDX, so that probably tells you what one I used
I was testing the long-mode present bit from CPUID in my bootsector. Originally I had the example, but I was able to cut off about 5-6 bytes by changing it. In a bootsector, that is a significant change!
But if anybody can find something shorter, by all means post it here!
Mike
I was testing the long-mode present bit from CPUID in my bootsector. Originally I had the example, but I was able to cut off about 5-6 bytes by changing it. In a bootsector, that is a significant change!
But if anybody can find something shorter, by all means post it here!
Mike
I've thought of the same way mentioned above.As Candy said,we may not make it more compact by adjusting the opcodes we use.
I am not sure if it is proper to put everything into a boot sector.Just think about what to do if you have something more to add(in your later version)?And it is not necessary to detect the CPU so early...You can put this in the following sectors...Or you may have trouble updating your design if you give the boot sector so much resposibility(or it will be hard to make your image compatible with some file system formats).
But if you insist may be you can try to change something in a larger range at the structure level to get it.Interesting challenge indeed(though not effective actually).
I am not sure if it is proper to put everything into a boot sector.Just think about what to do if you have something more to add(in your later version)?And it is not necessary to detect the CPU so early...You can put this in the following sectors...Or you may have trouble updating your design if you give the boot sector so much resposibility(or it will be hard to make your image compatible with some file system formats).
But if you insist may be you can try to change something in a larger range at the structure level to get it.Interesting challenge indeed(though not effective actually).
Hi,
I'm not sure if it makes sense optimizing 2 instructions for size when there's probably at least 100 instructions in the entire boot sector....
For an example, you'd probably save much more space by installing some exception handlers and then trying to enter long mode (whether it's supported or not). That way if long mode isn't supported your exception handler can display a "this CPU is too old message" and do an infinite loop, and everything will work as expected on all CPUs that don't support long mode (including 80286 which doesn't support 32-bit registers, 80386 which doesn't support CPUID, 80486 which doesn't support MSRs, etc).
Cheers,
Brendan
I'm not sure if it makes sense optimizing 2 instructions for size when there's probably at least 100 instructions in the entire boot sector....
For an example, you'd probably save much more space by installing some exception handlers and then trying to enter long mode (whether it's supported or not). That way if long mode isn't supported your exception handler can display a "this CPU is too old message" and do an infinite loop, and everything will work as expected on all CPUs that don't support long mode (including 80286 which doesn't support 32-bit registers, 80386 which doesn't support CPUID, 80486 which doesn't support MSRs, etc).
In my experience it normally takes about 2 weeks between "My 512 byte boot sector switches to protected/long mode" and "How do you detect RAM?" (or some other similar problem that requires real mode code that won't fit in their boot sector)...m wrote:I am not sure if it is proper to put everything into a boot sector.Just think about what to do if you have something more to add(in your later version)?And it is not necessary to detect the CPU so early...You can put this in the following sectors...Or you may have trouble updating your design if you give the boot sector so much resposibility(or it will be hard to make your image compatible with some file system formats).
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
i have to agree with brendan on this one, save it for your second stage
although i do a 386detect in my boot sector because i want to use reg32 in my bootsector and 386detect is quite simple, i save more complex CPU detection for my second stage/kernel init (i prefer this to the MS tactic of just assuming it will never run on anything less than a 386)
doing your CPU detection in your second stage, will also allow you more space to do it properly, including things you arent doing in your current version -- i load different versions of certain code for different capabilities (for example: 386-P5 i use a different paging system than i use for P6+ -- adding PAE to the latter while using a more efficient manager for the former)
although i do a 386detect in my boot sector because i want to use reg32 in my bootsector and 386detect is quite simple, i save more complex CPU detection for my second stage/kernel init (i prefer this to the MS tactic of just assuming it will never run on anything less than a 386)
doing your CPU detection in your second stage, will also allow you more space to do it properly, including things you arent doing in your current version -- i load different versions of certain code for different capabilities (for example: 386-P5 i use a different paging system than i use for P6+ -- adding PAE to the latter while using a more efficient manager for the former)
shouldnt matter since second stage should be RMode -- not PMode or LModeMike wrote:Right. I just wanted to detect 32/64 bit right away so I can load the proper second stage.
usually you will detect capabilities in second stage, then switch during second stage -- both PMode and LMode are easily done from the same code:
either load PMode and then jump to appropriate kernel code, which will then enable LMode (for 64bit kernel), or load PMode and then LMode (conditionally) and jump to kernel
basically, you should do as little as possible in your bootsector (for me, i do 386detect in the bootsector because the bootsector requires a 386 -- and i hang with an error on no386)
Key word: should... Which doesn't mean that I will.
I don't like having more stages than necessary. My boot sector was able to do that, read the FAT12 filesystem, and print understandable error messages and had several bytes to spare.
However I am thinking of redesigning my bootloader so it is multiboot-compliant. The preferred method of loading will still be with my normal bootloader, but there will be a multiboot entry point into the third stage so it can be loaded with GRUB.
But let's not drift too far off topic here. This is General Programming...
Mike
I don't like having more stages than necessary. My boot sector was able to do that, read the FAT12 filesystem, and print understandable error messages and had several bytes to spare.
However I am thinking of redesigning my bootloader so it is multiboot-compliant. The preferred method of loading will still be with my normal bootloader, but there will be a multiboot entry point into the third stage so it can be loaded with GRUB.
But let's not drift too far off topic here. This is General Programming...
Mike