SPARC using scanf() to read characters - c

Alrighty here's my problem. I am trying to take a character from a users input using scanf() and print it back out to them in SPARC Assembly. This code is simpler than what I am actually trying to do but it is the thing I am hung up on. It works fine with strings but for some reason not with characters.
SPARC code:
.section ".data"
prompt: .asciz "\nPlease enter your name: "
format: .asciz "%c"
format2: .asciz "Your name is:%c\n"
/* Program starts */
.align 4
.section ".text"
.global fun
fun:
save %sp, -96, %sp ! save the stack
set prompt, %o0 ! point o0 to the prompt
call printf ! call printf to print the prompt
nop
set format, %o0 ! point o0 to the input format string
set ch, %o1 ! point o1 at the input variable
call scanf ! get the input into this variable
nop
set format2, %o0 ! point o0 to the output format
set ch, %o1 ! point o1 to the string to be displayed
call printf ! print the string pointed by o1
nop
ret ! return
restore ! get out
C code:
#include <stdio.h>
char ch;
int main()
{
fun();
}

Related

Printf called from NASM segfaults on double value in xmm0

I have a C program linked into my NASM program to call printf. The C progam has two functions, one to print integer values and the other to print float values:
int Test_Print_2(int64_t value_passed_in)
{
printf ("value: %lu\n", value_passed_in);
return 0;
}
int Test_Print_2F(double value_passed_in)
{
printf ("Inside Test_Print - Float ");
printf ("q[0]: %f\n", value_passed_in);
//printf ("q[0]: %4.4lf\n", value_passed_in);
return 0;
}
The first program (Test_Print_2) works with no problem, but the second program (Test_Print_2F) throws a segfault. It doesn’t even print the line "Inside Test_Print - Float " If I comment out the print line then it does print the line "Inside Test_Print - Float " – so something is wrong with my format for printing doubles.
To print as integer, I call it from NASM like this:
movsd xmm0,[rdi] ; the values in the array pointed to by rdi are doubles
cvttsd2si rax,xmm0 ; convert to integer
%include "/opt/P01_SH/_Include_Utilities/ABI_Stack_Push.asm"
mov rdi,rax
call [rel Test_Print_2 wrt ..got]
%include "/opt/P01_SH/_Include_Utilities/ABI_Stack_Pop.asm"
That works and prints just the integer part of the floating point number. However, when I call it from NASM to print as a double like this:
movsd xmm0,[rdi]
%include "/opt/P01_SH/_Include_Utilities/ABI_Stack_Push.asm"
mov rax,1
call [rel Test_Print_2F wrt ..got]
%include "/opt/P01_SH/_Include_Utilities/ABI_Stack_Pop.asm"
it segfaults without printing anything. Both programs are linked in from the object file (I often link C object files into NASM).
Thanks for any help on this.

AT&T assembly + C functions. Using Scanf for string input

I'm trying to use scanf in assembly to get input.
As I know I have to push on stack arguments of functions in reverse order and then call function. It works fine with printf function but something is not quite right with scanf and place for input. Scanf should have 2 arguments. 1st is type of input (string,int, char etc) and 2nd is adress where to put it.
scanf(„%s” , buffer)
Is our goal i think.
My code:
.data
name: .ascii "What is your name?\n"
name2: .ascii "Your name is:"
formatScanf: .ascii "%s"
.bss
buffer: .size 100 #100 bytes for string input
.text
.globl main
main:
#Printing question #works fine
pushl $name
call printf
#Get answers
push $buffer #2nd argument for scanf
push $formatScanf #1st argument of scanf
call scanf
#Exiting
pushl $0
call exit
Error message:
lab3.s: Assembler messages:
lab3.s:8: Error: expected comma after name `' in .size directive
As compiler i'm using gcc with : " gcc -m32 Program.s -o run" command to have 32bit procesor work type, and to have C libuary linked automaticly.
What is wrong with it?
How should i use scanf in asm?
EDIT:
I should have used use .space not .size or .size buffer, 100
It compiles now.
EDIT 2:
COMPLETE CODE WITH USING SCANF C FUNCTION
#printf proba
.data
name2: .string "Your name is: %s "
formatScanf: .string "%s"
name: .string "What is your name?\n"
.bss
buffer: .space 100
.text
.globl main
main:
#Printing question #works fine
pushl $name
call printf
#Get answers
push $buffer #2nd argument for scanf
push $formatScanf #1st argument of scanf
call scanf
push $buffer
push $name2
call printf
#Exiting
pushl $0
call exit
In the GNU assembler, the .size directive specifies the size of a symbol. This is merely for informal purposes and has no effect whatsoever on the program. Most importantly, it does not specify the size of a buffer or variable or whatever.
In the GNU assembler, there is no notion of variable size or similar. To create a buffer of desired length, assemble the desired number of blank bytes and tack a label in front, like this:
buffer: .space 100
The .space directive assembles the given number of NUL bytes into the object. Optionally, you should afterwards set a symbol size for buffer so the output of nm -S is meaningful:
.size buffer, 100
Leaving this out won't hurt you, but then nm -S won't show size data for your symbol and doing so might make certain debug utilities less effective.

Unable to access correct global label data of assembly from C in linux

I have an assembly code (hello1.s) where global label A_Td is defined and I want to access all the long data values defined with global label A_Td from/inside C program.
.file "hello1.s"
.globl A_Td
.text
.align 64
A_Td:
.long 1353184337,1353184337
.long 1399144830,1399144830
.long 3282310938,3282310938
.long 2522752826,2522752826
.long 3412831035,3412831035
.long 4047871263,4047871263
.long 2874735276,2874735276
.long 2466505547,2466505547
As A_Td is defined in text section, so it is placed in code section and only one copy is loaded into memory.
Using yasm , I have generated hello1.o file
yasm -p gas -f elf32 hello1.s
Now, to access all the long data using global label A_Td , I have written following C code (test_glob.c) taking clue from here global label.
//test_glob.c
extern A_Td ;
int main()
{
long *p;
int i;
p=(long *)(&A_Td);
for(i=0;i<16;i++)
{
printf("p+%d %p %ld\n",i, p+i,*(p+i));
}
return 0;
}
Using following command I have compiled C program and then run the C code.
gcc hello1.o test_glob.c
./a.out
I am getting following output
p+0 0x8048400 1353184337
p+1 0x8048404 1353184337
p+2 0x8048408 1399144830
p+3 0x804840c 1399144830 -----> correct till this place
p+4 0x8048410 -1012656358 -----> incorrect value retrieved from this place
p+5 0x8048414 -1012656358
p+6 0x8048418 -1772214470
p+7 0x804841c -1772214470
p+8 0x8048420 -882136261
p+9 0x8048424 -882136261
p+10 0x8048428 -247096033
p+11 0x804842c -247096033
p+12 0x8048430 -1420232020
p+13 0x8048434 -1420232020
p+14 0x8048438 -1828461749
p+15 0x804843c -1828461749
ONLY first 4 long values are correctly accessed from C program. Why this is happening ?
What needs to be done inside C program to access the rest of data correctly ?
I am using Linux. Any help to resolve this issue or any link will be a great help. Thanks in advance.
How many bytes does "long" have in this system?
It seems to me that printf interprets the numbers as four byte signed integers, where the value 3282310938 has the hex value C3A4171A, which is above 7FFFFFFF (in decimal: 2147483647) which is the largest four byte positive signed number, and hence a negative value -1012656358.
I assume that the assembler just interprets these four byte numbers as unsigned.
If you would use %lu instead of %ld, printf would interpret the numbers as unsigned, and should show what you expected.

Redirecting the instruction pointer via stack overflow

I have been reading The Shellcoder's Handbook (2e) and have been trying to reproduce the stack overflow experiment on pages 18-23.
I have this code
void return_input (void)
{
char array[30];
gets (array);
printf(“%s\n”, array);
}
main()
{
return_input();
return 0;
}
Compile: gcc -fno-stack-protector -o overflow overflow.c
Dump of assembler code for function main:
0x080483ea <main+0>: push %ebp
0x080483eb <main+1>: mov %esp,%ebp
0x080483ed <main+3>: call 0x80483c4 <return_input>
0x080483f2 <main+8>: mov $0x0,%eax
0x080483f7 <main+13>: pop %ebp
0x080483f8 <main+14>: ret
We can overwrite the saved return address with the address of the call to return_input()
$ printf
"AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDD\xed\x83\x04\x08" | ./overflow
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDí
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDò
So this causes our input to be printed twice. However, I wasn't prompted for input a second time. Shouldn't the second call to return_input() result in a second call to gets()?
This probably has to do with what gets() reads from stdin.
Slightly altered version of your program:
#include <stdio.h>
int n = 1;
void return_input(void)
{
char array[30];
gets (array);
printf("%s\n", array);
if (n--) return_input();
}
int main(void)
{
return_input();
return 0;
}
If I just run it, I can type in 2 short strings (each followed by the Enter key), like so:
C:\gets.exe
qwe
qwe
123
123
And here both qwe and 123 get repeated on the screen (first time when I type them, second, when they get printed).
When I pipe programs input on Windows with the echo command, I get the following without a chance to enter the second string, gets() somehow manages to obtain garbage as input when it's called second time:
C:\echo qwe|gets.exe
qwe
№  ☺
So, something is wrong in how gets() reads piped input and that has nothing to do with stack overflows.

Printf problem with gcc on mmix

I have compiled the gcc 4.6.0 for mmix according to http://www.bitrange.com/mmix/install.html. After I try their simple hello world, or any other call to printf with more than the first string, only the first string gets printed. E.g.
lada#:~/f/c> cat hellommix.c
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
printf ("hello, %s\n", argc > 1 ? argv[1] : "world");
exit (0);
}
lada#:~/f/c> mmix-gcc hellommix.c
lada#:~/f/c> mmix ./a.out "abc"
hello, lada#:~/f/c>
The generated assembly looks like this:
# 1 "hellommix.c"
! mmixal:= 8H LOC Data_Section
.text ! mmixal:= 9H LOC 8B
.section .rodata
.p2align 2
LOC #+(4-#)&3
LC:0 IS #
BYTE "world",#0
.p2align 2
LOC #+(4-#)&3
LC:1 IS #
BYTE "hello, %s",#a,#0
.text ! mmixal:= 9H LOC 8B
.p2align 2
LOC #+(4-#)&3
.global main
main IS #
SUBU $254,$254,24
STOU $253,$254,16
ADDU $253,$254,24
GET $2,rJ
SET $3,$0
SUBU $0,$253,24
STOU $1,$0,0
SUBU $0,$253,12
STTU $3,$0,0
SUBU $0,$253,12
LDT $0,$0,0
SLU $0,$0,32
SR $0,$0,32
CMP $0,$0,1
BNP $0,L:2
SUBU $0,$253,24
LDO $0,$0,0
LDO $0,$0,8
JMP L:3
L:2 IS #
GETA $0,LC:0
L:3 IS #
GETA $5,LC:1
SET $6,$0
PUSHJ $4,printf
PUT rJ,$2
SETL $5,0
PUSHJ $4,exit
.data ! mmixal:= 8H LOC 9B
Try those:
put a fflush (stdout); before exiting. (though normally, posix' man 3 exit tells that all buffers are flushed; maybe something mmix specific)
Dump all arguments, just to see what's there.
-
for (int x=0; x!=argc; ++x) {
printf ("arg %d: \"%s\"\n", x, argv[x]);
}
Enter code:
setbuf(stdout,NULL);
after variable declaration.
Like this, just add setbuf(stdout,NULL); this code. On the first top only. Then you can do the code.

Resources