Gnu as suffix or opperand error - c

I am getting a suffix or operand error when I compile an old source code. It is generated from an inline assemble code.
ltr (unsigned val)
asm
("ltr %%eax /n/t"
:
: "a" (val)
);
I have read a lot of web pages/forums to find the syntax error but everything tell me the code is correct.
I am using gcc 4.4.1 on Mandriva 10 operating system

Use backslash to end the line.
Secondly it requires 16-bit argument, i.e:
("ltr %%ax \n\t"
Or from memory:
("ltr (%%eax) \n\t"

Related

Porting AT&T inline-asm inb / outb wrappers to work with gcc -masm=intel

I am currently working on my x86 OS. I tried implementing the inb function from here and it gives me Error: Operand type mismatch for `in'.
This may also be the same with outb or io_wait.
I am using Intel syntax (-masm=intel) and I don't know what to do.
Code:
#include <stdint.h>
#include "ioaccess.h"
uint8_t inb(uint16_t port)
{
uint8_t ret;
asm volatile ( "inb %1, %0"
: "=a"(ret)
: "Nd"(port) );
return ret;
}
With AT&T syntax this does work.
For outb I'm having a different problem after reversing the operands:
void io_wait(void)
{
asm volatile ( "outb $0x80, %0" : : "a"(0) );
}
Error: operand size mismatch for `out'
If you need to use -masm=intel you will need to insure that your inline assembly is in Intel syntax. Intel syntax is dst, src (AT&T syntax is reverse). This somewhat related answer has some useful information on some differences between NASM's Intel variant1 (not GAS's variant) and AT&T syntax:
Information on how you can go about translating NASM Intel syntax to GAS's AT&T syntax can be found in this Stackoverflow Answer, and a lot of useful information is provided in this IBM article.
[snip]
In general the biggest differences are:
With AT&T syntax the source is on the left and destination is on the right and Intel is the reverse.
With AT&T syntax register names are prepended with a %
With AT&T syntax immediate values are prepended with a $
Memory operands are probably the biggest difference. NASM uses [segment:disp+base+index*scale] instead of GAS's syntax of segment:disp(base, index, scale).
The problem in your code is that source and destination operands have to be reversed from the original AT&T syntax you were working with. This code:
asm volatile ( "inb %1, %0"
: "=a"(ret)
: "Nd"(port) );
Needs to be:
asm volatile ( "inb %0, %1"
: "=a"(ret)
: "Nd"(port) );
Regarding your update: the problem is that in Intel syntax immediate values are not prepended with a $. This line is a problem:
asm volatile ( "outb $0x80, %0" : : "a"(0) );
It should be:
asm volatile ( "outb 0x80, %0" : : "a"(0) );
If you had a proper outb function you could do something like this instead:
#include <stdint.h>
#include "ioaccess.h"
uint8_t inb(uint16_t port)
{
uint8_t ret;
asm volatile ( "inb %0, %1"
: "=a"(ret)
: "Nd"(port) );
return ret;
}
void outb(uint16_t port, uint8_t byte)
{
asm volatile ( "outb %1, %0"
:
: "a"(byte),
"Nd"(port) );
}
void io_wait(void)
{
outb (0x80, 0);
}
A slightly more complex version that supports both the AT&T and Intel dialects:
Multiple assembler dialects in asm templates On targets such as x86,
GCC supports multiple assembler dialects. The -masm option controls
which dialect GCC uses as its default for inline assembler. The
target-specific documentation for the -masm option contains the list
of supported dialects, as well as the default dialect if the option is
not specified. This information may be important to understand, since
assembler code that works correctly when compiled using one dialect
will likely fail if compiled using another. See x86 Options.
If your code needs to support multiple assembler dialects (for
example, if you are writing public headers that need to support a
variety of compilation options), use constructs of this form:
{ dialect0 | dialect1 | dialect2... }
On x86 and x86-64 targets there are two dialects. Dialect0 is AT&T syntax and Dialect1 is Intel syntax. The functions could be reworked this way:
#include <stdint.h>
#include "ioaccess.h"
uint8_t inb(uint16_t port)
{
uint8_t ret;
asm volatile ( "inb {%[port], %[retreg] | %[retreg], %[port]}"
: [retreg]"=a"(ret)
: [port]"Nd"(port) );
return ret;
}
void outb(uint16_t port, uint8_t byte)
{
asm volatile ( "outb {%[byte], %[port] | %[port], %[byte]}"
:
: [byte]"a"(byte),
[port]"Nd"(port) );
}
void io_wait(void)
{
outb (0x80, 0);
}
I have also given the constraints symbolic names rather than using %0 and %1 to make the inline assembly easier to read and maintain.. From the GCC documentation each constraint has the form:
[ [asmSymbolicName] ] constraint (cvariablename)
Where:
asmSymbolicName
Specifies a symbolic name for the operand. Reference the name in the assembler template by enclosing it in square brackets (i.e. ‘%[Value]’). The scope of the name is the asm statement that contains the definition. Any valid C variable name is acceptable, including names already defined in the surrounding code. No two operands within the same asm statement can use the same symbolic name.
When not using an asmSymbolicName, use the (zero-based) position of the operand in the list of operands in the assembler template. For example if there are three output operands, use ‘%0’ in the template to refer to the first, ‘%1’ for the second, and ‘%2’ for the third.
This version should work2 whether you compile with -masm=intel or -masm=att options
Footnotes
1Although NASM Intel dialect and GAS's (GNU Assembler) Intel syntax are similar there are some differences. One is that NASM Intel syntax uses [segment:disp+base+index*scale] where a segment can be specified inside the [] and GAS's Intel syntax requires the segment outside with segment:[disp+base+index*scale].
2Although the code will work, you should place all these basic functions in the ioaccess.h file directly and eliminate them from the .c file that contains them. Because you placed these basic functions in a separate .c file (external linkage) the compiler can't optimize them as well as it could. You can modify the functions to be of type static inline and place them in the header directly. The compiler will then have the ability to optimize the code by removing function calling overhead and reduce the need for extra loads and stores. You will want to compile with optimizations higher than -O0. Consider -O2 or -O3.
Special Notes Regarding OS Development:
There are many toy OSes (examples, tutorials, and even code on OSDev Wiki) that do not work with optimizations on. Many failures are due to bad/poor inline assembly or using undefined behaviour. Inline assembly should be used as a last resort. If your kernel doesn't run with optimizations on it is likely not a bug in the compiler (it is possible just not likely).
Heed the advice in #PeterCordes answer regarding port access that may trigger DMA reads.
It's possible to writing code that works with or without -masm=intel, using dialect alternatives for GNU C inline asm https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html (This is a good idea for headers that other people might include.)
It works like "{at&t stuff | intel stuff}": the compiler picks which side of the | to keep based on the current mode.
The major difference between AT&T vs. Intel syntax is that the operand-list is reversed, so usually you have something like "inb {%1,%0 | %0,%1}".
This is a version of #MichaelPetch's nice functions using dialect alternatives:
// make this a header: these single instructions can inline more cheaply
// than setting up args for a function call
#include <stdint.h>
static inline
uint8_t inb(uint16_t port)
{
uint8_t ret;
asm volatile ( "inb {%1, %0 | %0, %1}"
: "=a"(ret)
: "Nd"(port) );
return ret;
}
static inline
void outb(uint16_t port, uint8_t byte)
{
asm volatile ( "outb {%1, %0 | %0, %1}"
:
: "a"(byte),
"Nd"(port) );
}
static inline
void io_wait(void) {
outb (0x80, 0);
}
The Linux/Glibc sys/io.h macros sometimes use %w1 to expand a constraint to the 16-bit register name, but using types of the right size also works.
If you want a memory-barrier version of these to take advantage of the fact that in / out are (more or less) serializing like a locked instruction or mfence, add a "memory" clobber to stop compile-time reordering of memory access across it.
If a port I/O can trigger a DMA read of some other memory that you wrote recently, you might also need a "memory" clobber for that. (x86 has cache-coherent DMA so you wouldn't have had to explicitly flush it, but you can't let the compiler reorder it after an outb, or even optimize away an apparently dead store.)
There's no support in GAS for saving the old mode, so using .intel_syntax noprefix inside your inline asm leaves you no way know whether to switch back to .att_syntax or not.
But that wouldn't usually be sufficient anyway: you need to get the compiler to format operands in ways that match the syntax mode when filling in a template. e.g. the port number needs to expand to $imm or %dx (AT&T1) vs. dx or imm without the $ prefix.
Or for a memory operand, [rdi + rax*4 + 8] or 8(%rdi, %rax, 4).
But you still need to take care of reversing the operand list with { | } yourself; the compiler doesn't try to do that for you. It's purely a text-substitution into the template according to simple rules.
Footnote 1: AT&T disassembly by objdump -d bizarrely uses (%dx) for the port number in the non-immediate form, but GAS accepts %dx or (%dx) on input, so an "Nd" constraint is usable, simply expanding to the bare register name.

inline assembly in avr

void save_context(uint8_t index) {
context *this_context = contextArray + index;
uint8_t *this_stack = this_context->stack;
asm volatile("st %0 r0": "r"(this_stack));
}
I have something like this.
!!! I would like to store the registers r0 r1 r2... into my stack[] array.
What I am programming is the context switch. The context has the structure like this:
typedef struct context_t {
uint8_t stack[THREAD_STACK_SIZE];
void *pstack;
struct context_t *next;
}context;
My problem is that I am not able to pass the c variable "this_stack" to inline assembly. My aim is to store all the registers, stack pointer and SREG on my stack.
After compiling, it gives error:
Description Resource Path Location Type
`,' required 5_multitasking line 754, external location: C:\Users\Jiadong\AppData\Local\Temp\ccDo7xn3.s C/C++ Problem
I looked up the avr inline assembly tutorial. But I don't quite get a lot.
Could anyone help me?
asm volatile ("st %0 r0": "r"(this_stack));
There are several problems in that line: Wrong % print-modifier, missing , between the operands, incorrect constraint and missing description of side effects.
The memory access is supposed to use indirect addressing, so one way is to use indirect+displacement with "b"ase register Y or Z:
asm volatile ("std %a1+0, r0" "\n\t"
"std %a1+1, r1" "\n\t"
"..."
: "+m" (this_context->stack)
: "b" (this_stack));
Notice print modifier %a which prints R30 as Z and not as r30.
Operand 0 is just used to express that this_context->stack is being changed if you don't want the all-memory-clobber "memory". Moreover, there's no need for an intermediate variable for operand 1 because it's not altered: you can use just as well "b" (this_context->stack) for operand 1.
Alternatively, post-increment addressing on "e"xtended (pointer) registers X, Y or Z can be used:
asm volatile ("st %a1+, r0" "\n\t"
"st %a1+, r1" "\n\t"
"..."
: "=m" (this_context->stack), "+e" (this_stack));
"label" makes no sense, that should be a constraint. It also makes no sense trying to save the stack pointer into an array. It might make sense to load the stack pointer with the address of that array, but that's not the save_context.
Anyway, to get the value of SPL which is the stack pointer you can do something like this:
asm volatile("in %0, %1": "=r" (*this_stack) : "I" (_SFR_IO_ADDR(SPL)));
(There is a q constraint but at least my gcc version doesn't like it.)
To get true registers, for example r26 you can do:
register uint8_t r26_value __asm__("r26");
asm volatile("": "=r" (r26_value));
There is a constraint, "m", documented in the GCC manual, but it doesn't always work on AVR. Here is an example of how it should work from sanguino/bootloaders/atmega644p/ATmegaBOOT
asm volatile("...
...
"sts %0,r16 \n\t"
...
: "=m" (SPMCSR) : ... );
I have found "m" to be fragile though. If a function uses a variable in C code, outside of the inline assembly, the compiler may choose to place it in the Z register and it will try to use Z in assembler too. This causes an assembler error when used with the sts instruction. Looking at the assembler output from the C compiler is the best way to debug this kind of problem.
Rather than using an "m" constraint, you can just put the literal address you want into your assembler code. For an example, see pins_teensy.c, where timer_0_fract_count is not included in the :
asm volatile(
...
"sts timer0_fract_count, r24" "\n\t"

Switching between Intel and ATT mode in GCC

So I have this inline assembly code along with my C code, and I want to use intel syntax for this particular call to asm(), however I need to switch back to ATT syntax or else it will give a long list of errors.
asm(".intel_syntax prefix");
asm volatile (
"add %0, $1 \n\t"
: "=r" (dst)
: "r" (src));
asm(".att_syntax prefix");
Now it gives the following error
/tmp/ccDNa2Wk.s: Assembler messages:
/tmp/ccDNa2Wk.s:180: Error: no such instruction: `movl -16(%ebp),%eax'
/tmp/ccDNa2Wk.s:187: Error: no such instruction: `movl %eax,-12(%ebp)'
I dont understand how to fix the error, i have no call to movl in any part of my code.
Since you haven't yet accepted an answer (<hint><hint>), let me add a third thought:
1) Instead of having 3 asm statements, do it in 1:
asm(".intel_syntax prefix\n\t"
"add %0, 1 \n\t"
".att_syntax prefix"
: "=r" (dst)
: "r" (src));
2) Change your compile options to include -masm=intel and omit the 2 syntax statements.
3) It is possible to support both intel and att at the same time. This way your code works whatever value is passed for -masm:
asm("{addl $1, %0 | add %0, 1}"
: "=r" (dst)
: "r" (src));
I should also mention that your asm may not work as expected. Since you are updating the contents of dst (instead of overwriting it), you probably want to use "+r" instead of "=r". And you do realize that this code doesn't actually use src, right?
Oh, and your original asm is NOT intel format (the $1 is the give-away).
I would try to do the following tests:
In some C code not containing inline assembler insert the line
asm(".att_syntax prefix");
in multiple different locations. Then compile the C code to object files and disassemble these object files (compiling to assembler won't work for this test).
Then compare the disassembly of the original code with the disassembly of the code containing the ".att_syntax" lines.
If the line ".att_syntax prefix" indeed is the correct line for switching back to AT&T mode the disassemblies must be equal AND compiling must work without any errors.
In the next step take your code and compile to assembler instead of object code ("-S" option of GCC). Then you can look at the assembler code.
My idea is the following one:
If you use data exchange in inline assembler ("=r" and "r" for example) GCC needs to insert code that is doing the data exchange:
asm(".intel_syntax prefix");
// GCC inserts code moving "src" to "%0" here
asm volatile (
"add %0, $1 \n\t"
: "=r" (dst)
: "r" (src));
// GCC inserts code moving "%0" to "dst" here
asm(".att_syntax prefix");
This code inserted by GCC is of course in AT&T syntax.
If you want to use Intel syntax in inline assembly you have to use the ".att_syntax" and ".intel_syntax" instructions in the same inline assembly block, just like this:
// GCC inserts code moving "src" to "%0" here
asm volatile (
".intel_syntax prefix \n\t"
"add %0, $1 \n\t"
".att_syntax prefix \n\t"
: "=r" (dst)
: "r" (src));
// GCC inserts code moving "%0" to "dst" here

extended asm: invalid instruction suffix for 'mov'

Using i686-elf-gcc and i686-elf-ld to compile and link.
/tmp/ccyjfCee.s:25: Error: invalid instruction suffix for 'mov'
makefile:21: recipe for target 'Release/boot.o' failed
When I tried to modify movw %0, %%dx to movw $0x1, %%dx. It compiled and linked successfully. So I wonder why there is something wrong with the line. In light of .code16, the offset address of pStr should be 16bit, which fits into dx register well. What's wrong with it?
__asm__(".code16\n");
void printString(const char* pStr) {
__asm__ __volatile__ ("movb $0x09, %%ah\n\t"
"movw %0, %%dx\n\t"
"int $0x21"
:
:"r"(pStr)
:"%ah", "%dx");
}
void _start() {
printString("Hello, World");
}
Technically you can use the .code16gcc directive to generate 16 bit code and the %w0 substitution to force word sized register.
Note that the above will only let you create a program that will run in 16 bit real mode under DOS (after some postprocessing to get it to the proper format). If that's not what you want, you will need to use the appropriate OS system calls instead of int 0x21 and not write 16 bit code.

C Inline assembly - Operand type mismatch for 'fst'

Hey Im trying to learn how to write assembly code in my C programs. I understand integers in assembly but floats continue to trip me up.
double asmSqrt(double x) {
double o;
__asm__ ("fld %1;"
"fsqrt;"
"fst %0;"
: "=g" (o)
: "g" (x)
);
return o;
}
As you can see Im just trying to find the square root of x. But whenever I try to compile it I get an operand type mismatch error.
I followed the same syntax used here: http://www.codeproject.com/KB/cpp/edujini_inline_asm.aspx?display=Print
PS: Im using MinGW GCC on Windows XP
You need to explicitly specify which fld and fst instruction variants you want. Otherwise, the compiler doesn't know what size your operand is supposed to be. This code works for me here:
__asm__ ("fldl %1 ;"
"fsqrt ;"
"fstl %0 ;"
: "=g" (o)
: "g" (x)
);
You can use a disassembler to double-check that the right opcodes for 64-bit FLD and FST (DD/0 and DD/2) are getting emitted.
First, why are you doing this? The compiler can do square roots itself. You just call the proper math library function, enable optimization (so it will inline standard functions) and I'd be surprised if it doesn't do what you want. The result is platform independent (i.e. you can build for 64-bit if you want, or even a whole other architecture), easy to maintain code - much better!
If you insist on doing it the hard way, gcc can also help here (I've not actually tested this):
double asmSqrt(double x) {
__asm__ ("fsqrt" : "+t" (x));
return x;
}
The t constraint means put the value on the top of the floating-point stack - you don't have to care how it gets there. The + means to use the value for both input and output.
Edit: Oh, and if you do want to put things in registers yourself then you had better tell the compiler about that in the 'clobbers' section or you might overwrite something it has stored there.
double sqrt1(double n)
{
__asm{
fld n
fsqrt
}
}
call the method: double result = sqrt1((double)10) for example
Specify memory location "=m" instead of "=g". But best is to read this manual here: http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s4
Anyway, here is the solution:
double asmSqrt(double x) {
double o;
__asm__ ("fld %1;"
"fsqrt;"
"fst %0;"
: "=m" (o)
: "g" (x)
);
return o;
}

Resources