-3

For a class project I am implementing a kernel level network driver which makes use of writing various values to ports. I've created macros for outb and outw which all work fine, but outl continues to give compiler warnings. Defined like this:

#define outl(data, port)                \
do {                                    \
    asm volatile("outl  %l1, (%w0)"     \
        :                               \
        : "d" (port), "a" (data)        \
        : "memory", "cc" );             \
} while(0)

The compiler gives the error: invalid 'asm': '%l' operand isn't a label.

Yet if i define it like this:

#define outl(data, port)                \
do {                                    \
    asm volatile("outl  %1, %0"         \
        :                               \
        : "dN" (port), "a" (data)       \
        : "memory", "cc" );             \
} while(0)

I get this message from the assembler: Warning: using '%eax' instead of '%ax' due to 'l' suffix.

What am I doing wrong? What's the proper syntax to eliminate both of these warnings?

tVoss42
  • 554
  • 4
  • 16
  • Which of C and C++ are you programming in? Please remove the tag of the language you do not use. – fuz Apr 29 '17 at 20:42
  • How do you invoke the `outl` macro? What is the type of `data` in your invocation? – fuz Apr 29 '17 at 20:43
  • What do you expect `%l1` to do? – fuz Apr 29 '17 at 20:46
  • If you don't answer questions you receive in the comments, it is likely that your question is going to be closed for “unclear what you are asking” as you refuse to clarify. – fuz Apr 29 '17 at 20:50
  • `%l1` is for labels. you probably mean `%k1`. `k` is to request the 32-bit register form. – Michael Petch Apr 29 '17 at 20:53
  • Any reason you don't make a function `outl` put it in a header and mark it static inline? – Michael Petch Apr 29 '17 at 20:54
  • You also don't need `cc` since flags aren't altered by `out`, and `memory` isn't required as memory in the conventional sense isn't being modified. – Michael Petch Apr 29 '17 at 20:56

1 Answers1

1

Michael Petch had the correct answer. The class I'm in had actually already given us the first example, but clearly they never actually tested it.

I expected %l1 to specify the value was 32 bits, much like %b1 for 4 bits and %w1 for 16 bits. The solution was %k1.

tVoss42
  • 554
  • 4
  • 16
  • Actually, if the type of the operand is correct, no `k` modifier is needed. The `k` modifier is somewhat dangerous, for example, if the value is in `al` it blindly uses `eax` even when the rest of `eax` contains rubbish. Instead make sure that the operand has the right type in the first place (e.g. with an explicit cast). – fuz Apr 29 '17 at 21:18
  • @fuz : there is a reason I suggested (in my comment under the OP's question) to make the function `static inline` (I'd go further with adding `__attribute__((always_inline))` as well and put the function in a header. At least then you could have it check the types and promote types when possible. As you say you could alternatively explicitly cast `data` to `uint32_t` . – Michael Petch Apr 29 '17 at 21:32