Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Computing factorial, problems!

Status
Not open for further replies.

taskler

Programmer
Sep 7, 2010
5
0
0
SE
I get a segfault when running this.
I have several questions:
1. How do I print a register, for example eax?
2. Is the factorial function correct? should ret be in the end or could you use it in a cmp-clause?
3. Anything else?


.text # section declaration

# we must export the entry point to the ELF linker or
.global _start # loader. They conventionally recognize _start as their
# entry point. Use ld -e foo to override the default.

#pushl och popl ger problem pga 64bit, anvaend nedanstaende.
#as --32 -o math.o math.s ; ld -melf_i386 -s -o math math.o ; ./math

_start:

#leaves answer in eax, uses eax and ebx
#answer in eax, counter in ebx
#when calling function, N should be in ebx
fac:
movl $1, %eax
fac_loop:
cmp $1, %ebx
jmp fac_end
imul %ebx, %eax
subl $1, %ebx
jmp fac_loop
fac_end:
ret

# write our string to stdout

movl $len,%edx # third argument: message length
movl $5, %ebx # factorial of 5 is what we want to compute
jmp fac # compute it
movl $answer,%ecx # second argument: pointer to message to write
movl $1,%ebx # first argument: file handle (stdout)
movl $4,%eax # system call number (sys_write)
int $0x80 # call kernel

# and exit

movl $0,%ebx # first argument: exit code
movl $1,%eax # system call number (sys_exit)
int $0x80 # call kernel

.data # section declaration

answer:
.ascii "Factorial of 5 is: \n"
len = . - answer
 
fixed it up a bit. problem is how to print a register?
If I can do that it is a lot easier to test the program...





.text # section declaration

# we must export the entry point to the ELF linker or
.global _start # loader. They conventionally recognize _start as their
# entry point. Use ld -e foo to override the default.

#pushl och popl ger problem pga 64bit, anvaend nedanstaende.
#as --32 -o math.o math.s ; ld -melf_i386 -s -o math math.o ; ./math

#leaves answer in eax, uses eax and ebx and ecx
#answer in ecx, counter in ebx
#when calling function, N should be in ebx
fac:
movl $1, %eax
fac_loop:
cmp $1, %ebx
jmp fac_end
imul %ebx, %eax
subl $1, %ebx
jmp fac_loop
fac_end:
movl %eax, %ecx
ret

_start:

# write our string to stdout

movl $len,%edx # third argument: message length
movl $msg,%ecx # second argument: pointer to message to write
movl $1,%ebx # first argument: file handle (stdout)
movl $4,%eax # system call number (sys_write)
int $0x80 # call kernel

movl $3,%edx
movl $5, %ebx # factorial of 5 is what we want to compute
addl $0x48, %ebx
call fac # compute it
movl $1,%ebx # first argument: file handle (stdout)
movl $4,%eax # system call number (sys_write)
int $0x80 # call kernel

# and exit

movl $0,%ebx # first argument: exit code
movl $1,%eax # system call number (sys_exit)
int $0x80 # call kernel

.data # section declaration

msg:
.ascii "Factorial of 5 is: \n"
len = . - msg

#ans:
# .ascii "120\n"
# len2 = . - ans




 
What you will need to do is convert the numerical value in the register to an ASCII character string in memory. What you will have to do is keep dividing the value by ten and convert the modulus to an ASCII value. The last iteration occurs when the result of the division is 0.
CAVEAT: This will only work for integers. Also, it has been a few years since I have coded in ASM, snd this code is untested.

Code:
; I am only familiar with MASM style syntax, not ATT

.data
  numstr BYTE DUP 32  ; just an arbitary memory size.

.code
proc near CnvrtNum
  mov eax, Dividend  ; dword sized Dividend
  xor cx,cx
:div_loop
  xor edx, edx       ; zero out high order dword
  div 10d            ; result in eax, modulus in edx
  add dl, 30h        ; convert to ascii char
  push dl            ; save it to the stack
  inc cx             ; incr loop counter for next loop
  cmp eax, 0         ; if eax not 0, repeat
jne div_loop         ; 
  push ds            ; Change ES to DS
  pop es             ;
  lea di, numstr     ; DI points to 1st byte of Numstr
  cld                ;going to increment DI
:sto_loop
  pop al             ; pop highest order digit
  stosb              ; Store it to memory
loop sto_loop        ; keep doing it until CX = 0
  xor al, al         ; zero out al
  stosb              ; Store Null terminator
ret
 
Actually, after taking a second look, if you are wanting to convert EAX, the line:
div 10d ; result in eax, modulus in edx

should read:
div DWORD 10d ; result in eax, modulus in edx




 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top