LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 03-04-2009, 10:26 AM   #1
Zmyrgel
Senior Member
 
Registered: Dec 2005
Location: Finland
Distribution: Slackware, Ubuntu, OpenBSD
Posts: 1,004

Rep: Reputation: 36
Assembly prg won't work


I'm trying to get simple assembly program to do some small calculation and to print the result. Currently it goes through the assembler and linker without errors or warnings but it won't print anything and seems to exit with failure (1).

Also the debugging doesn't seem to work as it won't assign the break points.

Whats going on and how can I proceed with this?

Code:
.section .text
        .global _start

# The calculation
# 1444x = 1024x + 256x + 128x + 32x + 4x
_start:
          xorl      %eax, %eax # set eax to 0
          movw     $2, %bx    # variable to multiply (X)

          movw     %bx, %ax   # X
          shl      $10, %ax   # *1024
          pushw    %ax        # stack (1)
          movw     %bx, %ax   # X
          shl      $8, %ax    # *256
          pushw    %ax        # stack (2)
          movw     %bx, %ax   # X
          shl      $7, %ax    # *128
          pushw    %ax        # stack (3)
          movw     %bx, %ax   # X
          shl      $5, %ax    # *32
          pushw    %ax        # stack (4)
          movw     %bx, %ax   # X
          shl      $2, %ax    # *4
          pushw    %ax        # stack (5)

          popw     %bx        # stack (4)
          addw     %bx, %ax   # +4X
          popw     %bx        # stack (3)
          addw     %bx, %ax   # +32X     
          popw     %bx        # stack (2)
          addw     %bx, %ax   # +128X    
          popw     %bx        # stack (1)
          addw     %bx, %ax   # +256X    
	  popw     %bx        # stack (0)
          addw     %bx, %ax   # +1024X   
	  movl     %eax, %ecx #	store result for printing

          movl     $4, %eax   # syscall to use (write)
          movl     $1, %ebx   #	fd of result 1 = stdout
          movl     $4, %edx   # How much to read, 4 bytes
          int      $0x80      # call the kernel

	  movl     $1, %eax   # syscall	( 1 = exit )
	  xorl     %ebx, %ebx #	(exit value)
          int      $0x80      # call the kernel
          ret
Here's the stuff when I try to run and debug the above.

Code:
zmyrgel@cube zmyrgel-> as -gstabs -o stack.o stack.s
zmyrgel@cube zmyrgel-> ld -o stack stack.o          
zmyrgel@cube zmyrgel-> ./stack                      
zmyrgel@cube zmyrgel-> gdb stack                    
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(gdb) l
1	.section .text
2	        .global _start
3	
4	# The calculation
5	# 1444x = 1024x + 256x + 128x + 32x + 4x
6	_start:
7	          xorl      %eax, %eax # set eax to 0
8	          movw     $2, %bx    # variable to multiply (X)
9	
10	          movw     %bx, %ax   # X
(gdb) b 1
Breakpoint 1 at 0x8048054: file stack.s, line 1.
(gdb) r
Starting program: /home/zmyrgel/stack 

Program exited with code 01.
(gdb) q
zmyrgel@cube zmyrgel->

Last edited by Zmyrgel; 03-04-2009 at 11:27 AM. Reason: updated the code
 
Old 03-04-2009, 02:14 PM   #2
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian
Posts: 1,421

Rep: Reputation: 360Reputation: 360Reputation: 360Reputation: 360
You tried to put the break point at line 1:
Code:
1	.section .text
This line doesn't translate into executable code, try break 7 or even break _start.

The problem with your program is that sys_write expects a char* (pointer to byte) representing a string. You are passing a number which will be interpreted as a pointer (probably an address that your program doesn't own). I think it would be easier if you call your assembly function from C and print the result using the C library.
Code:
################
# assemby file
################

.section .text
        .global calculation

# The calculation
# 1444x = 1024x + 256x + 128x + 32x + 4x
calculation:
          # save the callee-save registers on the stack
          push %ebp
          push %ebx
          push %edi
          push %esi
          push %edi

          # calculation code, put result in %eax...

          # restore callee-save registers
          pop %edi
          pop %esi
          pop %edi
          pop %ebx
          pop %ebp
          ret
Code:
/*********
 * C file
 *********/

#include <stdio.h>

int calculation(); /* defined in assembly file */

int main()
{
    int result = calculation();
    printf("calculation() = %d\n", result);
    return 0;
}

Last edited by ntubski; 03-04-2009 at 02:15 PM. Reason: separate C and asm
 
Old 03-04-2009, 02:36 PM   #3
Zmyrgel
Senior Member
 
Registered: Dec 2005
Location: Finland
Distribution: Slackware, Ubuntu, OpenBSD
Posts: 1,004

Original Poster
Rep: Reputation: 36
Quote:
Originally Posted by ntubski View Post
You tried to put the break point at line 1:
Code:
1	.section .text
This line doesn't translate into executable code, try break 7 or even break _start.
I tried it but it gave same result.

Quote:
Originally Posted by ntubski View Post
The problem with your program is that sys_write expects a char* (pointer to byte) representing a string. You are passing a number which will be interpreted as a pointer (probably an address that your program doesn't own). I think it would be easier if you call your assembly function from C and print the result using the C library.
Unfortunately that isn't an option. At least not yet. This is assembly programming course homework and it needs to be assembly. The calculation with stack is the main idea. I just wanted to have it print the result too but its quite difficult. Good point on the pointer issue. I'm not sure how to do it in assembly. I've read lot of tutorials that use write call with predefined 'hello world' string but I don't know how mimic that in my program.
 
Old 03-04-2009, 03:47 PM   #4
johnsfine
Senior Member
 
Registered: Dec 2007
Distribution: Mepis, Centos
Posts: 4,012

Rep: Reputation: 731Reputation: 731Reputation: 731Reputation: 731Reputation: 731Reputation: 731Reputation: 731
Quote:
Originally Posted by Zmyrgel View Post
This is assembly programming course homework and it needs to be assembly.
That's a rotten way to teach assembly.

A beginner will get so bogged down in the inability to do I/O that it will interfere with learning anything interesting.

Beginning assembly (and most of the time, even advanced assembly) should be taught as writing subroutines to be called by an instructor provided main program.

But that is all in your instructor's control, not your control.

Quote:
I just wanted to have it print the result too but its quite difficult.
Do you know the basic concepts of converting a number to base ten text (described below in case you don't)? Coding that in assembler is a useful beginner exercise, so give it a try.

Generate the digits right to left in a (bottom checked) loop:
At each step divide the working value by 10 producing both a quotient (which becomes the new working value) and a remainder, which is added to the ascii code of '0' to produce the next digit (right to left).
Loop until the working value is zero.

You'll need some thought on where/how to store the digits as you create them right to left. But that still should be in the range of beginning assembler.
 
Old 03-04-2009, 04:31 PM   #5
Zmyrgel
Senior Member
 
Registered: Dec 2005
Location: Finland
Distribution: Slackware, Ubuntu, OpenBSD
Posts: 1,004

Original Poster
Rep: Reputation: 36
Quote:
Originally Posted by johnsfine View Post
That's a rotten way to teach assembly.

A beginner will get so bogged down in the inability to do I/O that it will interfere with learning anything interesting.

Beginning assembly (and most of the time, even advanced assembly) should be taught as writing subroutines to be called by an instructor provided main program.
Yeah, I think later in the course we start to use C too.

Quote:
Originally Posted by johnsfine View Post
Do you know the basic concepts of converting a number to base ten text?
You mean converting base ten value to binary or what? Number -> text conversion seems pretty odd consept at these alcohol levels

I removed the printing of the number from the code and used debugger on it. I fixed the small thing that I didn't set the eax to 0 after last placement in the stack... I could have kept the value in the register too but I chose the former way for now.

Last edited by Zmyrgel; 03-04-2009 at 04:33 PM.
 
Old 03-04-2009, 04:42 PM   #6
johnsfine
Senior Member
 
Registered: Dec 2007
Distribution: Mepis, Centos
Posts: 4,012

Rep: Reputation: 731Reputation: 731Reputation: 731Reputation: 731Reputation: 731Reputation: 731Reputation: 731
Quote:
Originally Posted by Zmyrgel View Post
You mean converting base ten value to binary or what?
No the opposite: Converting a number from the internal form used by the computer (calling that "binary" can cause confusion I wanted to avoid) to base ten.

Some mixed C and psuedo code:
Code:
int work = the number to convert;
char* pointer = the buffer address plus the length of the buffer;
do { // bottom checked loop
   int remainder = work % 10;
   work = work / 10;
   *(--pointer) = remainder + '0';
} while ( work != 0 )
pointer now points at the text to print but you need to compute the length;
int length=buffer address plus length of buffer minus pointer;
Now, just code the same thing in assembler and add it to what you've coded so far.

Quote:
seems pretty odd consept at these alcohol levels
I could get that bit of code right while drunk, but I don't test that very often. I'll just hope you were joking.
 
Old 03-04-2009, 04:50 PM   #7
Zmyrgel
Senior Member
 
Registered: Dec 2005
Location: Finland
Distribution: Slackware, Ubuntu, OpenBSD
Posts: 1,004

Original Poster
Rep: Reputation: 36
Quote:
Originally Posted by johnsfine View Post
No the opposite: Converting a number from the internal form used by the computer (calling that "binary" can cause confusion I wanted to avoid) to base ten.
Yeah, sorry. Mixed those already. What do you mean by 'case confusion'? I thought computers used binary... or rather electric currents to do stuff internally.

Quote:
Originally Posted by johnsfine View Post
I could get that bit of code right while drunk, but I don't test that very often. I'll just hope you were joking.
Nah, not drunk. Just a little tipsy... or I was a little while ago. Now I'm just getting sleepy, should be at school in 7 hours so I'd better go get some Z's before that.
 
Old 03-04-2009, 06:48 PM   #8
johnsfine
Senior Member
 
Registered: Dec 2007
Distribution: Mepis, Centos
Posts: 4,012

Rep: Reputation: 731Reputation: 731Reputation: 731Reputation: 731Reputation: 731Reputation: 731Reputation: 731
Quote:
Originally Posted by Zmyrgel View Post
What do you mean by 'case confusion'? I thought computers used binary.
Computers do use binary, but that fact is not relevant to programming (even in assembly language) as often as you might expect.

When you are converting input or output from or to some base, the fact that the computer uses binary isn't very relevant but can be very confusing.

If I want to input a number in binary, I need code to convert that number from base 2 (binary) to internal form. If I confuse myself by calling internal form "binary", that is a converter from binary to binary.

When you code an assembly language instruction to add, subtract, multiply, divide, etc. the numbers in two registers, you should normally think of that just as add, subtract, multiply or divide of those numbers, not of those binary numbers.

There are various overflow issues where it is important to pay more attention to the way the number is really stored. But even then, it can be easier to think about, and just as well connected to the underlying reality, if you think a register holds an 8 digit base 16 number, rather than a 32 digit base 2 number.
 
Old 03-05-2009, 01:14 AM   #9
Zmyrgel
Senior Member
 
Registered: Dec 2005
Location: Finland
Distribution: Slackware, Ubuntu, OpenBSD
Posts: 1,004

Original Poster
Rep: Reputation: 36
Quote:
Originally Posted by johnsfine View Post
If I want to input a number in binary, I need code to convert that number from base 2 (binary) to internal form. If I confuse myself by calling internal form "binary", that is a converter from binary to binary.

When you code an assembly language instruction to add, subtract, multiply, divide, etc. the numbers in two registers, you should normally think of that just as add, subtract, multiply or divide of those numbers, not of those binary numbers.

There are various overflow issues where it is important to pay more attention to the way the number is really stored. But even then, it can be easier to think about, and just as well connected to the underlying reality, if you think a register holds an 8 digit base 16 number, rather than a 32 digit base 2 number.
This bit is just confusing me more
 
Old 03-05-2009, 10:15 PM   #10
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian
Posts: 1,421

Rep: Reputation: 360Reputation: 360Reputation: 360Reputation: 360
Quote:
Originally Posted by Zmyrgel View Post
I tried it but it gave same result.
oops, I didn't test that first, it seems to work with break 8, I don't understand why...


I think johnsfine's point is that you have to be careful not to confuse a binary string (eg "101010"), with the internal storage format. Everything is stored as bytes internally, what the bytes mean depends on how you use them. In gdb you can decide which format to print values in:
Code:
(gdb) set $x = 42
(gdb) p/o $x
$4 = 052
(gdb) p/x $x
$5 = 0x2a
(gdb) p/d $x
$6 = 42
(gdb) p/t $x
$7 = 101010
(gdb) p/f $x
$8 = 5.88545355e-44
(gdb) p/a $x
$9 = 0x2a
(gdb) p/c $x
$10 = 42 '*'
(gdb) p/s $x
$11 = 42

(gdb) set $s = "010101"
(gdb) p/o $s
$1 = 030010020
(gdb) p/x $s
$2 = 0x601010
(gdb) p/d $s
$3 = 6295568
(gdb) p/f $s
$4 = 3.1104238698574848e-317
(gdb) p/a $s
$5 = 0x601010
(gdb) p/c $s
$6 = 16 '\020'
(gdb) p/s $s
$7 = 0x601010 "010101"
(gdb) x/o $s
0x601010:       06114030460
(gdb) x/x $s
0x601010:       0x31303130
(gdb) x/d $s
0x601010:       825241904
(gdb) x/f $s
0x601010:       2.56393307e-09
(gdb) x/a $s
0x601010:       0x313031303130
(gdb) x/c $s
0x601010:       48 '0'
(gdb) x/s $s
0x601010:        "010101"
 
Old 03-06-2009, 02:12 AM   #11
Zmyrgel
Senior Member
 
Registered: Dec 2005
Location: Finland
Distribution: Slackware, Ubuntu, OpenBSD
Posts: 1,004

Original Poster
Rep: Reputation: 36
Ok, that clears it up.

Then just to figure out the fundamental thing on the next asm assignment ... and to convert it to work on my Linux machine as I highly doubt the DOS system calls will work on it
 
  


Reply

Tags
assembly


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
*.prg mobile linux package maciejus Linux - Laptop and Netbook 0 05-04-2007 11:56 AM
Command line prg keshu_lk Linux - Kernel 2 11-09-2006 09:44 PM
Email Prg bluewater Linux - Newbie 6 04-22-2006 01:12 AM
[Assembly] how do i work Y86 code at debian sarge? Mathsniper Programming 3 04-08-2005 04:02 PM
problem executing prg with anjuta freeindy Linux - Software 4 04-03-2005 11:28 PM


All times are GMT -5. The time now is 02:55 PM.

Main Menu
 
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: @linuxquestions
Open Source Consulting | Domain Registration