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.
Related
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.
I am new to C, so forgive me if this query is basic.
I want to call main() from another function, and make the program run infinitely. The code is here:
#include <stdio.h>
void message();
int main()
{
message();
return 0;
}
void message()
{
printf("This is a test message. \n");
main();
}
I expect to see this program run infinitely. However, it runs for some time and then stops suddenly. Using a counter variable, which I printed alongside the test message, I found that the statement "This is a test message." is printed 174608 times after which I get an error message
Segmentation fault (core dumped)
and the program terminates. What does this error mean? And why does the program only run 174608 times (why not infinitely)?
You have stack overflow from infinite recursion. Make infinite loop in main:
int main()
{
while (1)
{
//...
}
}
The mutual recursion costs stack space. If you put the recursion in main() itself, the compiler may recognise the tail recursion, and replace it by iteration. [for fun and education, don't try this at home, children ...] :
#include <stdio.h>
void message();
int main()
{
message();
return main();
}
void message()
{
printf("This is a test message. \n");
}
GCC recognises the tail recursion in optimisation level=2 and above.
main.s output for gcc -O2 -S main.c:
.p2align 4,,15
.globl main
.type main, #function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
.p2align 4,,7
.p2align 3
.L4:
call message
jmp .L4
.size main, .-main
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3"
.section .note.GNU-stack,"",#progbits
This is not equivalent to while(1) {...} or for(;;) {...}, which give you infinite loops.
Every time a function(for example, main() or message()) is called, some values are pushed into the stack. When functions are called too many times, your stack get filled, and finally overflow, giving you a "stack overflow" error.
Note that this error has nothing to do with this site, although they happen to have the same name :)
When I try to store something from register to memory, I received Segmentation fault error. As I used gdb to debug line by line, it shows up Program received signal SIGSEGV when comes to the line of stb.
What I tried to do is to implement the standard C strcat function in PowerPC Assembly.
Here's the main C program, pretty simple.
#include<stdio.h>
extern char *mystrcat(char *first, char *second);
int main(){
char *first, *second, *third;
first = "ab";
second = "cd";
third = mystrcat(first, second);
printf("%s\n", third);
return 0;
}
And this is my mystrcat.s powerpc assembly file.
.text
.align 2
.globl mystrcat
mystrcat:
mr %r5, %r3
.L1:
lbz %r6, 0(%r5)
cmpdi %r6, 0
beq .L2
addi %r5, %r5, 1
b .L1
.L2:
lbz %r6, 0(%r4)
stb %r6, 0(%r5)
addi %r4, %r4, 1
addi %r5, %r5, 1
cmpdi %r6, 0
beq .L3
b .L2
.L3:
blr
Before the L2 label is the process finding the end of the first string.
Gdb showed up "Program received signal SIGSEGV" at the second line after L2 label.
The stb %r6, 0(%r5) command seems raised the error.
But I just don't get it why it cannot figure out address by 0(%r5).
I've tried other command seems like stbx or stbu but no one works.
Thank you for everyone can give me even just little piece of advice.
Update:
I realized this has something to do with memory.
Since the memory for string is readonly, is there a way that I can allocate new memory inside assembly code? I tried "bl malloc" and "nop" and the behavior beyonds my understanding.
In your main function, you try to concatenate 2 strings with the destination one having no room enough to copy the source one at the end.
Trying to add a (kind of implicit) memory allocation in your function mystrcat will introduce confusion.
Note that the segmentation fault also appears using the standard strcat that you want to mimic.
You should fix you main function, writing something like that:
#include <stdio.h>
extern char *mystrcat(char *first, char *second);
int main(){
char first[8] = "ab";
char *second, *third;
second = "cd";
third = mystrcat(first, second);
printf("%s\n", third);
return 0;
}
String literals are stored in read only section of memory. Any attempt to modify string literals results in undefined behavior.
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();
}
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.