Code: Select all
if (tchar == 0x61)
{
b_print_string("key was 'a'\n");
}
else
{
b_print_string("key was not 'a'\n");
}
-Ian
Code: Select all
if (tchar == 0x61)
{
b_print_string("key was 'a'\n");
}
else
{
b_print_string("key was not 'a'\n");
}
Code: Select all
// gcc -o testc1.o -c testc1.c -m64 -nostdlib -nostartfiles -nodefaultlibs -fomit-frame-pointer
// ld -T app.ld -o testc1.app testc1.o
void b_print_string(const char *str);
void b_print_char(const char chr);
unsigned char b_input_wait_for_key(void);
int main(void)
{
unsigned char tchar = 0x65;
b_print_char(tchar);
b_print_string("Hello world, from C!\nHit a key: ");
tchar = b_input_wait_for_key();
if (tchar == 'a')
{
b_print_string("key was 'a'\n");
}
else
{
b_print_string("key was not 'a'\n");
}
return 0;
}
// C call to os_print_string
// C passes the string address in RDI instead of RSI
void b_print_string(const char *str)
{
asm volatile ("call 0x00100010" :: "S"(str)); // Make sure string is passed in RSI
}
void b_print_char(const char chr)
{
asm volatile ("call 0x00100018" :: "a"(chr));
}
// C call to os_input_key_wait
unsigned char b_input_wait_for_key(void)
{
asm volatile ("call 0x00100038");
}
Code: Select all
// C call to os_input_key_wait
unsigned char b_input_wait_for_key(void)
{
asm volatile ("call 0x00100038");
}
Code: Select all
// C call to os_input_key_wait
unsigned char b_input_wait_for_key(void)
{
unsigned char r;
asm volatile ("call 0x00100038" : "=a"(r));
return r;
}
The ABI always has the return value in RAX.Alexis211 wrote:How can you be sure GCC will keep your return value in rax ?
Code: Select all
Something like:
void b_input_wait_for_key(unsigned char chr)
{
asm volatile ("call 0x00100038" : "=a"(chr));
}
Instead of: (gives a "warning: control reaches end of non-void function" error)
unsigned char b_input_wait_for_key(void)
{
asm volatile ("call 0x00100038");
}
Code: Select all
void b_input_wait_for_key(unsigned char chr)
{
asm volatile ("call 0x00100038" : "=a"(chr) : "0" (chr));
return chr;
}
unsigned char b_input_wait_for_key(void)
{
unsigned char chr;
asm volatile ("call 0x00100038" : "=a" (chr));
return chr;
}
Code: Select all
.global some_function
some_function .equ absolute_address_of_function
Hi: the solution is very simple. GCC has optimized your code since as far as it can tell, the value of tchar cannot change.ReturnInfinity wrote:Sure. Here is it:
Thanks,Code: Select all
// gcc -o testc1.o -c testc1.c -m64 -nostdlib -nostartfiles -nodefaultlibs -fomit-frame-pointer // ld -T app.ld -o testc1.app testc1.o void b_print_string(const char *str); void b_print_char(const char chr); unsigned char b_input_wait_for_key(void); int main(void) { unsigned char tchar = 0x65; b_print_char(tchar); b_print_string("Hello world, from C!\nHit a key: "); tchar = b_input_wait_for_key(); if (tchar == 'a') { b_print_string("key was 'a'\n"); } else { b_print_string("key was not 'a'\n"); } return 0; }
-Ian
Let's wait and see.Owen wrote:Erm, no. Making tchar volatile won't help here.
Maybe, just maybe, GCC is saying that the function is defined as returning a non-void type, and it doesn't have a return statement in there at all. I dunno, maybe the compiler doesn't know how to say what it wants to say or something.Basically, when GCC says "No return value for function returning non-void", what it's really saying is "The return value is gonna be junk.
Use a function pointer if all you're doing is calling a function with the inline assembly:Code: Select all
unsigned char b_input_wait_for_key(void) { asm volatile ("call 0x00100038"); }
Code: Select all
typedef unsigned char (*func)(void);
func b_input_wait_for_key = (func) 0x100038;
While I agree with you in part, I'd like to know how you'd approach a global variable that's affected by external state changes - eg, a mutex that gets unlocked by an IRQ.Years of experience programming have shown me one thing: There is never a reason for a variable to be declared volatile. I'm being serious, never.
Or what about a location in memory that gets changed by hardware?pcmattman wrote:While I agree with you in part, I'd like to know how you'd approach a global variable that's affected by external state changes - eg, a mutex that gets unlocked by an IRQ.Years of experience programming have shown me one thing: There is never a reason for a variable to be declared volatile. I'm being serious, never.
Wierd Al wrote: You think your Commodore 64 is really neato,
What kind of chip you got in there, a Dorito?
You sound like a linux evangelist - this is not the linux kernel where all instances of the volatile keyword have disappeared into assembly stubs because people didn't want to see volatile... </countertroll>Owen wrote:Years of experience programming have shown me one thing: There is never a reason for a variable to be declared volatile. I'm being serious, never.
If it does work, it's a really ugly hack.Let's wait and see.Owen wrote:Erm, no. Making tchar volatile won't help here.
GCC's __builtin_atomic (Or MVSC's Interlocked*)Firestryke31 wrote:Or what about a location in memory that gets changed by hardware?pcmattman wrote:While I agree with you in part, I'd like to know how you'd approach a global variable that's affected by external state changes - eg, a mutex that gets unlocked by an IRQ.Years of experience programming have shown me one thing: There is never a reason for a variable to be declared volatile. I'm being serious, never.
Code: Select all
#define ATOMIC_LOAD(_type, _addr) (*((volatile _type*) _addr))
#define ATOMIC_STORE(_type, _addr, _val) (*((volatile type*) _addr) = _val)
tchar will never have an address, because it's address is never taken, and it will be kept in registers. So GCC will shrug and go "Well, that was pointless". Basically, any access of tchar from outside that function would break aliasing rulesgravaera wrote:Let's wait and see.Owen wrote:Erm, no. Making tchar volatile won't help here.