inline-Assembler compiler error messages - inline-assembly

The machine i use is 64-bit, I wrote inline assembly code like this
__asm__ (
"mov %cl TEMP_CHAR \n"
"xor %eax, %eax \n"
"mov %eax, A \n"
"rcr %eax, %cl \n"
"mov TEMP_B, %eax \n"
)
Using gcc compiler,
When I compile with it using commaand line
It turns out errors as follow
/tmp/ccK8W7qx.s: Assembler messages:
/tmp/ccK8W7qx.s:177 : Error: suffix or operands invalid for 'rcr'
I wonder why this happens. Could anybody help me out?

AT&T syntax has the operands the other way: rcr %cl, %eax. You'll probably want to change the other intructions, too.

Related

How to use m5 in gem5-20 linking it with my own C++ program?

In gem5-20, I can build the m5 utility by using.
scons build/<arch>/out/m5
But actually I don’t know how to link M5 to my C++ code.
Some necessary operations are mentioned at the end of this document, but I hope to get more specific guidance.
http://www.gem5.org/documentation/general_docs/m5ops/
Has anyone done it,please help me.
Thanks!
Best wishes!
On gem5 046645a4db646ec30cc36b0f5433114e8777dc44 I can do:
scons -C util/m5 build/x86/out/m5
gcc -static -I include -o main.out main.c util/m5/build/x86/out/libm5.a
with:
main.c
#include <gem5/m5ops.h>
int main(void) {
m5_exit(0);
}
Or for ARM:
sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
scons -C util/m5 build/aarch64/out/m5
aarch64-linux-gnu-gcc -static -I include -o main.out main.c \
util/m5/build/aarch64/out/libm5.a
An official example can also be found at: gem5-resources/src/simplem5_exit.c with instructions at on the README.
And here is one using the m5_exit_addr variant, which uses the memory version of the m5op instead of instruction, which can also be used from KVM for example: https://gem5-review.googlesource.com/c/public/gem5/+/31219/7
But in practice, I often just don't have the patience for this business, so I just misbehave and add raw assembly directly as shown here muahahaha e.g.:
#if defined(__x86_64__)
#define LKMC_M5OPS_CHECKPOINT __asm__ __volatile__ (".word 0x040F; .word 0x0043;" : : "D" (0), "S" (0) :)
#define LKMC_M5OPS_DUMPSTATS __asm__ __volatile__ (".word 0x040F; .word 0x0041;" : : "D" (0), "S" (0) :)
#elif defined(__aarch64__)
#define LKMC_M5OPS_CHECKPOINT __asm__ __volatile__ ("mov x0, 0; mov x1, 0; .inst 0xFF000110 | (0x43 << 16);" : : : "x0", "x1")
#define LKMC_M5OPS_DUMPSTATS __asm__ __volatile__ ("mov x0, 0; mov x1, 0; .inst 0xFF000110 | (0x41 << 16);" : : : "x0", "x1")
More general m5op information can also be found at: What are pseudo-instructions for in gem5?
Related:
How to use m5 in gem5-20 linking it with my own C++ program?
Tested on Ubuntu 20.04.

How to use the m5ops in gem5 such m5_exit and m5_dump_stats in se mode

I know this a trivial question but I am having difficulties in running the m5ops in gem5,
lets take for example the m5-exit.c file that has been provided by gem5, in the test programs, how would I compile it and link it to the file m5op_x86.S
Currently this is the way I am compiling and linking it:
gcc m5-exit.c -I ~/Desktop/gem5_86/gem5/include -o test ~/Desktop/gem5_86/gem5/util/m5/m5op_x86.S
the error i get:
/tmp/ccXsGX3d.o: relocation R_X86_64_16 against undefined symbol `M5OP_ARM' can not be used when making a PIE object; recompile with -fPIC
the directory i am in is:
gem5/tests/test-progs/m5-exit/src
the code for m5-exit.c is from the gem5 directory found here
This is a copy of: How to use m5 in gem5-20 which was deleted on my other answer, since my previous DRY link-only answer was removed followed by an unsuccessful (although correct, but not enough users who care) dupe close attempt.
On gem5 046645a4db646ec30cc36b0f5433114e8777dc44 I can do:
scons -C util/m5 build/x86/out/m5
gcc -static -I include -o main.out main.c util/m5/build/x86/out/libm5.a
with:
main.c
#include <gem5/m5ops.h>
int main(void) {
m5_exit(0);
}
Or for ARM:
sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
scons -C util/m5 build/aarch64/out/m5
aarch64-linux-gnu-gcc -static -I include -o main.out main.c \
util/m5/build/aarch64/out/libm5.a
But in practice, I often just don't have the patience for this business, so I just misbehave and add raw assembly directly as shown here muahahaha e.g.:
#if defined(__x86_64__)
#define LKMC_M5OPS_CHECKPOINT __asm__ __volatile__ (".word 0x040F; .word 0x0043;" : : "D" (0), "S" (0) :)
#define LKMC_M5OPS_DUMPSTATS __asm__ __volatile__ (".word 0x040F; .word 0x0041;" : : "D" (0), "S" (0) :)
#elif defined(__aarch64__)
#define LKMC_M5OPS_CHECKPOINT __asm__ __volatile__ ("mov x0, 0; mov x1, 0; .inst 0xFF000110 | (0x43 << 16);" : : : "x0", "x1")
#define LKMC_M5OPS_DUMPSTATS __asm__ __volatile__ ("mov x0, 0; mov x1, 0; .inst 0xFF000110 | (0x41 << 16);" : : : "x0", "x1")
More general m5op information can also be found at: What are pseudo-instructions for in gem5?
Tested on Ubuntu 20.04.

Simple calculator program in lex and yacc not giving output

I am trying to write a very simple calculator program using lex and yacc but getting stuck in printing the output. The files are:
calc.l:
%{
#include "y.tab.h"
extern int yylval;
%}
%%
[0-9]+ {yylval = atoi(yytext); return NUMBER;}
[ \t] ;
\n return 0;
. return yytext[0];
%%
calc.y:
%{
#include <stdio.h>
void yyerror(char const *s) {
fprintf(stderr, "%s\n", s);
}
%}
%token NAME NUMBER
%%
statement: NAME '=' expression
| expression {printf(" =%d\n", $1);}
;
expression: expression '+' NUMBER {$$ = $1 + $3;}
| expression '-' NUMBER {$$ = $1 - $3;}
| NUMBER {$$ = $1;}
;
The commands I have used:
flex calc.l
bison calc.y -d
gcc lex.yy.c calc.tab.c -lfl
./a.out
After running the last command although the program takes input from the keyboard but does not print anything, simply terminates. I didn't get any warning or error while compiling but it doesn't give any output. Please help.
You have no definition of main, so the main function in -lfl will be used. That library is for flex programs, and its main function will call yylex -- the lexical scanner -- until it returns 0.
You need to call the parser. Furthermore, you need to call it repeatedly, because your lexical scanner returns 0, indicating end of input, every time it reads a newline.
So you might use something like this:
int main(void) {
do {
yyparse();
} while (!feof(stdin));
return 0;
}
However, that will reveal some other problems. Most irritatingly, your grammar will not accept an empty input, so an empty line will trigger a syntax error. That will certainly happen at the end of the input, because the EOF will cause yylex to return 0 immediately, which is indistinguishable from an empty line.
Also, any error encountered during the parse will cause the parse to terminate immediately, leaving the remainder of the input line unread.
On the whole, it is often better for the scanner to return a newline token (or \n) for newline characters.
Other than the main function which you don't require, the only thing in -lfl is a default definition of yywrap. You could just define this function yourself (it only needs to return 1), or you could avoid the need for the function by adding
%option noyywrap
to your flex file. In fact, I usually recommend
%option noyywrap noinput nounput
which will avoid the compiler warnings (which you didn't see because you didn't supply -Wall when you compiled the program, which you should do.)
Another compiler warning will be avoided by adding a declaration of yylex to your bison input file before the definition of yyerror:
int yylex(void);
Finally, yylval is declared in y.tab.h, so there is no need for extern int yylval; in your flex file. In this case, it doesn't hurt, but if you change the type of the semantic value, which you will probably eventually want to do, this line will need to be changed as well. Better to just eliminate it.

Memcheck reports unitialised values when accessing local variables down the stack

I encountered a problem that Memcheck reports uninitialized values and I think these are perfectly legal. I managed to create a small example program that exhibits this behavior. I would like to know if Memcheck is really wrong and what can be done about it. (Is there any solution besides adding the errors into a suppression file?)
To reproduce this, I made the program below. It runs function go that puts 0x42 on the stack, calls og (this pushes the address of the next instruction leave on the stack), then in og it stores esp+4 into global variable a.
The stack looks like this:
| address of `leave` instruction | pc = a[-1]
| 0x42 | a points here, answer = a[0]
If I build it and run Valgrind,
gcc -g -m32 main.c go.S -o main
valgrind --track-origins=yes ./main
Valgrind thinks that the value in variable pc (and answer, if you put it in the if instead) is undefined. I checked with debugger that the values there actually are what I wanted.
==14160== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==14160== Command: ./main
==14160==
==14160== Conditional jump or move depends on uninitialised value(s)
==14160== at 0x804847D: print (main.c:18)
==14160== by 0x80484B0: ??? (go.S:19)
==14160== by 0x8048440: main (main.c:8)
==14160== Uninitialised value was created by a stack allocation
==14160== at 0x80484AC: ??? (go.S:19)
==14160==
==14160== Use of uninitialised value of size 4
==14160== at 0x80484B1: ??? (go.S:20)
==14160== by 0x8048440: main (main.c:8)
==14160== Uninitialised value was created by a stack allocation
==14160== at 0x80484AC: ??? (go.S:19)
If I debug from Valgrind with --vgdb-error=0 and print the definedness, it says that all the bits are undefined.
(gdb) p &pc
$1 = (int *) 0xfea5e4a8
(gdb) mo xb 0xfea5e4a8 4
ff ff ff ff
0xFEA5E4A8: 0x9e 0x84 0x04 0x08
The value at 0xfea5e4a8 is
(gdb) x/x 0xfea5e4a8
0xfea5e4a8: 0x0804849e
and
(gdb) x/i 0x0804849e
0x804849e <go+10>: leave
(gdb)
main.c
#include<stdio.h>
int *a;
extern void go();
int main() {
go();
printf("finito\n");
return 0;
}
int print() {
int answer = a[0];
int pc = a[-1];
// use the vars
if (pc == 0x42) {
printf("%d\n", 0);
}
}
go.S
.text
.globl go
go:
pushl %ebp
movl %esp, %ebp
pushl $0x42
call og
leave
ret
og:
addl $4, %esp
movl %esp, a
sub $4, %esp
call print
ret
The problem is this sequence of code:
addl $4, %esp
movl %esp, a
sub $4, %esp
When you move %esp up valgrind will mark everything below the new stack pointer position as undefined, and it will stay that way even after you move it back.
It's not safe anyway, because if a signal hit between the add and sub then that stack really might get overwritten (in 32 bit code - in 64 bit code there is a "red zone" below the pointer that is safe but valgrind knows about that).

"first use" error when change the code in lex file

Given a .l file like this:
%{
#include "y.tab.h"
%}
%%
[ \t\n]
"if" return IF_TOKEN ;
"while" return ELSE_TOKEN ;
. yyerror("Invalid Character");
%%
int yywrap(void){
return 1;
}
and a .y file like this:
%{
#include <stdio.h>
void yyerror(char *);
%}
%token IF_TOKEN ELSE_TOKEN MINUS_TOKEN DIGIT_TOKEN
%%
program :expr {printf("program Accepted!!!");};
expr : IF_TOKEN | DIGIT_TOKEN ;
%%
void yyerror(char *s){
fprintf(stderr, "%s\n", s);
}
int main(){
yyparse();
return 0;
}
I use these 3 commands to compile these 2 files (my lex file named p.l and my yacc file named p.y):
flex p.l
yacc -d p.y
gcc lex.yy.c y.tab.c
It is compiled with no error. But when I changed "return ELSE_TOKEN" to "return WHILE_TOKEN", I got this error and got no output file:
p.l: In function ‘yylex’:
p.l:10:8: error: ‘WHILE_TOKEN’ undeclared (first use in this function)
"while" return WHILE_TOKEN ;
^
p.l:10:8: note: each undeclared identifier is reported only once for each function it appears in
Also when I change "while" to "else" and add a new rule like:
"for" return FOR_TOKEN ;
I get the same error. How can I correct the code to work correctly?
You didn't add:
%token WHILE_TOKEN FOR_TOKEN
to the grammar, so the header didn't contain a definition for WHILE_TOKEN or FOR_TOKEN, so the compilation of the lexical analyzer failed.