Page 1 of 1
AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 3:58 am
by ScropTheOSAdventurer
So, after an rm -rf command that was written in the wrong context, I was redoing my OS (which had only gotten to the point of having interrupts and a custom GDT). This time I figured I would do my outportb and inportb functions in assembly, which I thought was better than hackish inline assembly:
Code: Select all
.global outportb
.type outportb, @function
outportb:
movb 4(%esp), %al # the byte sized value
movw 5(%esp), %dx # our port, right?
outb %al, %dx
ret
.global inportb
.type inportb, @function
inportb:
movw 4(%esp), %dx
inb %dx, %al # since AL is part of EAX, this should satisfy the System V ABI
ret
Their C headers:
Code: Select all
void outportb(uint16_t port, uint8_t thevalue);
uint8_t inportb(uint16_t port);
However, the C function that called it apparently did this in assembly when it called it (compare it with the corresponding C code):
Code: Select all
1000aa: 6a 0e push $0xe
1000ac: 68 d4 03 00 00 push $0x3d4
1000b1: e8 4f 01 00 00 call 100205 <outportb>
Why isn't it pushing the arguments the OTHER way around? And why isn't it specifying that they should be a byte and a short respectively (the assembly is in AT&T syntax)? These are my first two questions.
Now, my second question resulted in what happened after I changed my outportb to be more cooperative with the C code (in other words, make it so DX got the first two bytes on the top of the stack (if you skip the return address, of course) and al got the byte below that. Changed code:
Code: Select all
outportb:
movw 4(%esp), %dx
movb 6(%esp), %al
outb %al, %dx
ret
However, when I used QEMU and GDB together, when I stepped through the first instruction of outportb (with the C call being the same one I talked about prior), EDX became 0x3D4. However, upon stepping through the NEXT one, EAX didn't change from zero to 0xE at all. Is QEMU and my cross compiler going nuts, or am I just doing a mistake only a newbie would? Any help would be appreciated.
NOTE:
I accidentally posted this when it was only half done, so if you saw only half the post, sorry, my bad!
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 5:28 am
by jnc100
ScropTheOSAdventurer wrote:Why isn't it pushing the arguments the OTHER way around? And why isn't it specifying that they should be a byte and a short respectively (the assembly is in AT&T syntax)? These are my first two questions.
Now, my second question resulted in what happened after I changed my outportb to be more cooperative with the C code (in other words, make it so DX got the first two bytes on the top of the stack (if you skip the return address, of course) and al got the byte below that.
The answer to all of these is that you do not understand the calling convention your compiler is using. Have a look
here.
Regards,
John.
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 5:28 am
by sortie
This happens because you forgot to read the
System_V_ABI. The compiler doesn't work the way you naively expect or guess. The values on the stack are four byte aligned and pushed in reverse order.
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 5:34 am
by ScropTheOSAdventurer
I am so sorry about that! Forgetting the very ABI I am designing my code for is what I get for working overnight......... I feel like such a moron right now
EDIT: Solved the AL problem. It had to do with the compiler pushing the two arguments as 32 bits. I was getting the high bits of 0x3D4 when I tried to fetch the value to send to the port, which of course was just zeros... Why is the compiler sending both of those arguments as 32 bits though?
EDIT 2: Doesn't the uint* types need to be exact?
EDIT 3: @Sortie, I DID read the ABI when I started developing. I just forgot about it; I got tired and the reptile brain kicked in. No offense, but please don't be as condescending as you just were again.
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 5:57 am
by Bender
The intel manual will obviously give a more accurate explanation. It's by design I guess.
IIRC for performance reasons the stack needs to be aligned, so say you pushed a byte to the stack, and then called another function, the CPU will push the n-byte address to the stack (n=2,4,8), making your stack misaligned.
From Intel 2B:
The address-size attribute of the stack segment determines the stack pointer size (16, 32 or 64 bits). The operand-size attribute of the current code segment determines the amount the stack pointer is decremented (2, 4 or 8 bytes).
Also, the compiler is pushing your arguments by value, so something like:
if the assembler is in 32-bit mode, it will actually mean,
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 5:59 am
by ScropTheOSAdventurer
Well, in any case, I got my VGA cursor working properly now
. Thanks for all the help in pointing out my (mostly stupid) mistakes.
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 6:23 am
by sortie
ScropTheOSAdventurer wrote:Why is the compiler sending both of those arguments as 32 bits though? Doesn't the uint* types need to be exact?
The fixed-width types must behave as if they are that exact-width, but only from the C programmer's viewpoint. The C programming language standard doesn't even really tell that a stack exists (just that values are preserved when returning from calls). Thus the exact layout of the stack and the calling convention is entirely up to the implementation and standardized in the ABI. It is possible to implement this in many ways, this is just one of many ways of doing it. The C programming language does mandate an implicit type promotion to int (if smaller than an int) in every single expression, so passing parameters smaller than an int as an int makes some sense. The reason the values are passed like this on the System V ABI is mostly just a result of alignment requirements, the stack has to be suitably aligned (4-byte aligned, though actually gcc expects it to be 16-byte aligned, otherwise SSE intrinsics or higher-than-4-byte alignments of stack variable will give you problems) and passing everything as 4-byte variables makes this simpler. All of this is internals, as a C programmer you never would know the difference.
ScropTheOSAdventurer wrote:@Sortie, I DID read the ABI when I started developing. I just forgot about it; I got tired and the reptile brain kicked in. No offense, but please don't be as condescending as you just were again.
I'm sorry, I didn't mean to be offensive, I intended to be helpful. Your original post gave me the impression you had mostly disregarded the ABI and that you didn't know it. I often see programmers try to interact with C code from assembly where they obviously didn't know the calling convention, I wrongly assumed this was another such case. Perhaps I didn't phrase my post well enough; I had just woken up and posted from my phone. It is crucial to remember the ABI carefully when writing assembly, though, even if you are tired: Very subtle and nasty bugs can hide this way. I usually don't write assembly files for routines like this (unless I must), I prefer compiler builtins or inline assembly (though that is a minefield of its own) as they are much more maintainable and the compiler can understand them better.
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 6:48 am
by ScropTheOSAdventurer
I don't like inline assembly that much, mostly because if you are not careful, you can end up accidentally lying to the compiler and everything just hits the fan when the code is executed. Plus, you might not even KNOW you lied, until a new compiler version comes out that behaves differently.... I like it either black or white; C code or assembly.
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 6:53 am
by Bender
ScropTheOSAdventurer wrote:I don't like inline assembly that much, mostly because if you are not careful, you can end up accidentally lying to the compiler and everything just hits the fan when the code is executed. Plus, you might not even KNOW you lied, until a new compiler version comes out that behaves differently.... I like it either black or white; C code or assembly.
......and also because it's compiler specific. Example GCC's and MSVC's inline assembler are completely different.
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 6:58 am
by sortie
Except assembler files are also highly ABI specific and that most of gccs extensions are available in other compilers for that ABI.
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 11:23 am
by bwat
ScropTheOSAdventurer wrote:So, after an rm -rf command that was written in the wrong context, I was redoing my OS (which had only gotten to the point of having interrupts and a custom GDT).
Please tell us that you've now got backup routines in place! It only takes a handful of shell commands to set up both a backup script and version control for a project. Your time is too precious to be spent redoing previous work.
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 2:42 pm
by ScropTheOSAdventurer
Well, I have a Github project, but I got lazy and stopped updating it.
I need to make sure I update it from now on; I've learned my lesson. I am just happy I hadn't gotten very far in the OS. I do have to dispute the claim though that my time is too precious to redo stuff; I am on summer vacation.
Re: AL not being recognized as part of EAX? (and more...)
Posted: Mon May 26, 2014 3:23 pm
by sandras
"don't waste your time or time will waste you"
Re: AL not being recognized as part of EAX? (and more...)
Posted: Tue May 27, 2014 12:09 pm
by ScropTheOSAdventurer
I am lucky I just pushed my project to my github repo; the bootable usb drive I was working with (has lubuntu on it) that had my OS project on it just randomly overheated. I think I blew something inside. In any case though, my OS is safe
. Thanks for reminding me guys to use Github.