[SOLVED] How do I execute the OUT instruction in assembly?
Posted: Sat Dec 28, 2019 8:40 pm
I'm trying to implement the outb functionality without resorting to inline assembly.
Currently, I'm using the bare bones example from the wiki to test this by enabling the cursor, setting its position, and writing "Hello, World!" to the screen.
When using the outb funtion from the wiki, the text "Hello, World!" appears and the cursor is placed in the expected location.
When I call my assembly procedure to do outb, the kernel appears to hang.
I suspect this is due to me misunderstanding the i-386 System V ABI.
Here is my assembly procedure that attempts to use outb:
It is exposed to C code with the following header:
And just for reference, this is the inline assembly implementation from the wiki:
Combuster mentioned in another post that he had an implementation available, but the link appears to be broken.
viewtopic.php?f=1&t=15381&p=110436&hili ... on#p110436
I looked at the assembly generated for the inline example during compilation and tried to copy that in my implementation, but to no avail.
What am I missing here?
Currently, I'm using the bare bones example from the wiki to test this by enabling the cursor, setting its position, and writing "Hello, World!" to the screen.
When using the outb funtion from the wiki, the text "Hello, World!" appears and the cursor is placed in the expected location.
When I call my assembly procedure to do outb, the kernel appears to hang.
I suspect this is due to me misunderstanding the i-386 System V ABI.
Here is my assembly procedure that attempts to use outb:
Code: Select all
.section text
.global my_outb
# This procedure executes the outb instruction.
my_outb:
# According to the x86 System V ABI found at
# http://www.sco.com/developers/devspecs/abi386-4.pdf
# The first argument is located at offset 8(%ebp) and the
# second argument is at offset 12(%ebp).
# Since the C function signature is
# extern void my_outb(uint16_t port, uint8_t value)
# the port number should be at 8(%ebp) and the value should be at 12(%ebp).
movw 8(%ebp), %dx # first argument (a word containing the port number)
movb 12(%ebp), %al # second argument (a byte containing the value)
outb %al, %dx # write the byte in al to the port in dx
Code: Select all
#ifndef PORT_H
#define PORT_H
extern void my_outb(uint16_t port, uint8_t value);
#endif
Code: Select all
static inline void inline_outb(uint16_t port, uint8_t val)
{
asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) );
/* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in 8b. (N constraint).
* Wider immediate constants would be truncated at assemble-time (e.g. "i" constraint).
* The outb %al, %dx encoding is the only option for all other cases.
* %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port number a wider C type */
}
viewtopic.php?f=1&t=15381&p=110436&hili ... on#p110436
I looked at the assembly generated for the inline example during compilation and tried to copy that in my implementation, but to no avail.
What am I missing here?