Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › Factorial in Arm Assembly programming
New Posts  All Forums:Forum Nav:

# Factorial in Arm Assembly programming

So we have to do a homework for my computer organization class which is doing a factorial in arm assembly. The professor gave us the information that we need to do and I am understanding a bit of it but I am kinda lost also. We have to do a iterative and a recursive functions of the factorial.
Code:
``````Iteration:
int ifact (int n) {
int f = 1;
while (n > 0) {
f *= n;
n--;
}
return f;

recursive:

int rfact (int n) {
if (n == 0) {
return 1;
}
else {
return n * rfact(n-1);
}
}
}```
```

This is what I got so far:
Code:
``````.global _start

_start:
ldr r3,=_tests                  @load whatever is in _tests value into r3
@iteration
ldr r0,[r3]                     @R0:= MEM[R3] = whatever the value is loaded through the _test value
mov r1,#1                       @load #1 into register 1
bl  ifact                       @branch with link into ifact function

@recursive
ldr r0,[r3]                     @R0:= MEM[R3] = whatever the value is loaded through the _test value.
bl      rfact                   @branch with link into rfact function

ifact:
cmp r0,#0                       @compare R0 to #0
mulgt r1,r0,r1                  @if(R0 >  0) R1:= R0 * R1
subgt r0,r0,#1                  @if(R0 > 0) decrement r0
bgt ifact                       @if(R0 > 0) branch into loop
bx lr                           @return with link register.

rfact:

cmp r0,#0                       @compare R0 with the #0
moveq r0,#1                     @if (R0 == 0) Set the result to 1 and go to return.
iloop:
b iloop                         @infinite loop so the program doesn't close```
```

The iteration is what I kinda understand but for the recursive part I don't know how would you do it for the return n * rfact(n-1). I was thinking about the mulne r0,r0,r0-#1 but looking at it if I do a b rfact after that, wouldn't the r0 not decrement while if I sub r0,r0,#1 then it would just give me a different answer in the outcome. The _test value is the value 0x05 so I know the answer should be 120. I am also running this on QEMU and some reason it doesn't want to display the output. Thanks for reading and hope someone can help clear this up for me.
I don't know any ARM assembly, but I would say as a general rule when you are coding with recursion you should start by hitting your default / base case first, then work your way through the rest of the logic.

It is an entirely different way to think, and you might want to try to avoid the confusing infinite loops by making sure your base case is properly stopping the stack growth.
 Nightrider (17 items) Commodore 64 (10 items)
CPUMotherboardGraphicsRAM
3930k x79 gd45 PLUS GTX Titan Crucial Ballistix Sport VLP
Hard DriveHard DriveHard DriveCooling
HyperX 3k Intel 320 Seagate Barracuda Swifttech H220
CoolingCoolingOSOS
Swifttech 220QP Corsair SP120 Windows 8.1 Pro Windows 10 Pro
OSOSMonitorMonitor
Windows 7 Home Ubuntu 15.4 QNIX 2710 Catleap 2B
Keyboard
Ducky - Cherry MX Red
CPUMotherboardGraphicsRAM
3570k DZ77GA - 70K GTX670-DC2-4GD5  MV-3V4G3D/US
Hard DriveCoolingOSOS
HyperX 3k CM 212 + Win 7 64 ubuntu
PowerCase
Seventeam 850w modular CS-NT-ZERO-2
 Nightrider (17 items) Commodore 64 (10 items)
CPUMotherboardGraphicsRAM
3930k x79 gd45 PLUS GTX Titan Crucial Ballistix Sport VLP
Hard DriveHard DriveHard DriveCooling
HyperX 3k Intel 320 Seagate Barracuda Swifttech H220
CoolingCoolingOSOS
Swifttech 220QP Corsair SP120 Windows 8.1 Pro Windows 10 Pro
OSOSMonitorMonitor
Windows 7 Home Ubuntu 15.4 QNIX 2710 Catleap 2B
Keyboard
Ducky - Cherry MX Red
CPUMotherboardGraphicsRAM
3570k DZ77GA - 70K GTX670-DC2-4GD5  MV-3V4G3D/US
Hard DriveCoolingOSOS
HyperX 3k CM 212 + Win 7 64 ubuntu
PowerCase
Seventeam 850w modular CS-NT-ZERO-2
In assembler it helps to break it up into individual actions
For the line
Return n*rfact(n-1)
You're really doing 4 differerent actions

You're subtracting 1 from n
You're calling rfact
You're multiplying the result by n
You're returning the result of that
 SolusIgnis (21 items) 2 Watts (6 items) Huh?! (13 items)
CPUCPUCPUMotherboard
i7-3820 Xeon Phi 31S1P Copressor (WIP) Xeon Phi 31S1P Copressor (WIP) ASRock X79 Extreme6
GraphicsRAMHard DriveCooling
XFX Reference 6950 Samsung Magic RAM Crucial M4 Cosair H80
OSMonitorMonitorMonitor
Windows 8.1 Pro HannSpree HF205 1600x900 ASUS VH239H 1920x1080 ASUS VH239H 1920x1080
CMStorm Quick Fire Pro, Cherry MX Blue Thermaltake Oversoar RX-I MadCatz RAT 9 Saitek Cyborg V.5
OtherOtherOther
Thrustmaster HOTAS Warthog TrackIR 5 Saitek Pro Combat Pedals
CPUMotherboardRAMHard Drive
Marvell PXA510 D2Plug DDR3
Optical DriveCooling
Pssh! Who needs optical drives Passive
CPUOS
i386 MS-DOS
 SolusIgnis (21 items) 2 Watts (6 items) Huh?! (13 items)
CPUCPUCPUMotherboard
i7-3820 Xeon Phi 31S1P Copressor (WIP) Xeon Phi 31S1P Copressor (WIP) ASRock X79 Extreme6
GraphicsRAMHard DriveCooling
XFX Reference 6950 Samsung Magic RAM Crucial M4 Cosair H80
OSMonitorMonitorMonitor
Windows 8.1 Pro HannSpree HF205 1600x900 ASUS VH239H 1920x1080 ASUS VH239H 1920x1080
CMStorm Quick Fire Pro, Cherry MX Blue Thermaltake Oversoar RX-I MadCatz RAT 9 Saitek Cyborg V.5
OtherOtherOther
Thrustmaster HOTAS Warthog TrackIR 5 Saitek Pro Combat Pedals
CPUMotherboardRAMHard Drive
Marvell PXA510 D2Plug DDR3
Optical DriveCooling
Pssh! Who needs optical drives Passive
CPUOS
i386 MS-DOS
^ ... Recursion in general is pretty easy. I think what you guys are failing to address is how you would do it in ARM. The algorithm can also be found in like a million places. The thing most people have trouble with is how you have to allocate space on the stack for your return address and what your current computed variable(s) is/are. It's a whole different ball game from other languages in general. Loops in assembly aren't too bad, jumps and whatnot are easy to get used to. Recursion is probably one of the harder aspects to understand.

I've only had experience with MIPS, but the general thing you have to do is:
2. Save your current relevant variable
3. Call the function again with your next value.

At then end you need some cleanup to synthesize your results.

In fact, through just a bit of googling "ARM Recursion Example", you can in fact cheat on your assignment:
http://people.cs.umass.edu/~%20verts/cmpsci201/spr_2004/Lecture_20_2004-03-29_Recursion.pdf
Thanks for the tip there stolemyowncar.

so what I am prolly going to do now is something like this for recursion
Code:
``````_start:
ldr r3,=_tests                  @load whatever is in _tests value into r3
@recursive
ldr r0,[r3]                     @R0:= MEM[R3] = whatever the value is loaded through the _test value.
ldr r7,r0
bl      rfact                   @branch with link into rfact f

rfact:
push {lr}
sub r0,r0,#1
mul r7,r0,r7
cmp r0, #0
move r0,#1
beq rfact_done
b rfact
rfact_done:
pop {lr}
bx lr```
```

I notice I did over complicate the problem as I thought I was suppose to only use one variable but apparently my professor told me we can use two.
Lol I've been working on this today too I'm Greg in Johnson's class if you go to UTA. I couldnt figure out where the output would show either so can't help you with that. I'll post if it randomly shows up for me between now and Tuesday
 Project: Aiuto Arredo (16 items) Project Sophos (23 items) Server (11 items)
CPUMotherboardGraphicsGraphics
Intel 3930k Asus P9X79 Deluxe  EVGA GTX 670 2GB 2670-KR EVGA GTX 670 2GB 2670-KR
RAMHard DriveCoolingCooling
G.Skill Sniper 16GB  Western Digital Caviar Black 1Tb EK Supreme LTX CPU Plexi/Nickel waterblock EK GTX 670 Plexi/Copper waterblock
CoolingCoolingCoolingOS
EK GTX 670 Plexi/Copper waterblock  Dual Swiftech 655-B Pumps with Bitspower Top Two XSPC RX480 Radiators Windows 7-64 bit
MonitorPowerCaseMouse
3 Dell S2340L 23" Cooler Master 1000w Silent Pro Custom Oak Desk Logitech G700
CPUMotherboardGraphicsGraphics
AMD 1100T 3.3Ghz @ 4.012Ghz Asus Sabertooth 990FX Sparkle GTX 560TI EVGA Geforce GTX 460 Fermi
RAMHard DriveHard DriveOptical Drive
Patriot G2 Western Digital Caviar Blue Western Digital Caviar Blue none - their ancient
CoolingCoolingCoolingCooling
EK-Supreme LTX CPU Water Block - Acetal EK-VGA Supreme HF High Performance GPU Water Bl... Tejava glass bottle Swiftech MCP-655B
CoolingOSOSMonitor
Masterkleer 1/2" ID 3/4" OD tubing Ubuntu 10.10 64-bit Windows 7 64-bit I-inc 22"
MonitorKeyboardPowerCase
I-inc 22" Logitech k-300 Gaming Keyboard Thermaltake Toughpower 775 Watt Power Supply Corsair 800D
Logitech G700 Eh they're useless Scythe Kaze Master Pro
CPUCPUMotherboardGraphics
Intel Xeon E5-2670  Intel Xeon E5-2670  Intel S2600CP2 Headless
RAMHard DriveHard DriveHard Drive
Samsung ECC 2Rx4 PC3 10600R E1-P1 Western Digital Black Western Digital Blue Western Digital Blue
OSPowerCase
Centos 7x64 EVGA 750w Bronze Fractal Design Core 3500
 Project: Aiuto Arredo (16 items) Project Sophos (23 items) Server (11 items)
CPUMotherboardGraphicsGraphics
Intel 3930k Asus P9X79 Deluxe  EVGA GTX 670 2GB 2670-KR EVGA GTX 670 2GB 2670-KR
RAMHard DriveCoolingCooling
G.Skill Sniper 16GB  Western Digital Caviar Black 1Tb EK Supreme LTX CPU Plexi/Nickel waterblock EK GTX 670 Plexi/Copper waterblock
CoolingCoolingCoolingOS
EK GTX 670 Plexi/Copper waterblock  Dual Swiftech 655-B Pumps with Bitspower Top Two XSPC RX480 Radiators Windows 7-64 bit
MonitorPowerCaseMouse
3 Dell S2340L 23" Cooler Master 1000w Silent Pro Custom Oak Desk Logitech G700
CPUMotherboardGraphicsGraphics
AMD 1100T 3.3Ghz @ 4.012Ghz Asus Sabertooth 990FX Sparkle GTX 560TI EVGA Geforce GTX 460 Fermi
RAMHard DriveHard DriveOptical Drive
Patriot G2 Western Digital Caviar Blue Western Digital Caviar Blue none - their ancient
CoolingCoolingCoolingCooling
EK-Supreme LTX CPU Water Block - Acetal EK-VGA Supreme HF High Performance GPU Water Bl... Tejava glass bottle Swiftech MCP-655B
CoolingOSOSMonitor
Masterkleer 1/2" ID 3/4" OD tubing Ubuntu 10.10 64-bit Windows 7 64-bit I-inc 22"
MonitorKeyboardPowerCase
I-inc 22" Logitech k-300 Gaming Keyboard Thermaltake Toughpower 775 Watt Power Supply Corsair 800D
Logitech G700 Eh they're useless Scythe Kaze Master Pro
CPUCPUMotherboardGraphics
Intel Xeon E5-2670  Intel Xeon E5-2670  Intel S2600CP2 Headless
RAMHard DriveHard DriveHard Drive
Samsung ECC 2Rx4 PC3 10600R E1-P1 Western Digital Black Western Digital Blue Western Digital Blue
OSPowerCase
Centos 7x64 EVGA 750w Bronze Fractal Design Core 3500
Quote:
Originally Posted by glinuxÂ

Lol I've been working on this today too I'm Greg in Johnson's class if you go to UTA. I couldnt figure out where the output would show either so can't help you with that. I'll post if it randomly shows up for me between now and Tuesday

Yeah I am in his class also. He posted something to our email saying that we should do something like qemu-system-arm -s -M versatilepb -daemonize -d in_asm,cpu,exec -singlestep -kernel -hw05.bin -D hw05.log which is suppose to give you each step in the log file of how your programming is working. I did that and found a lot of mistake on mine. First off the mult with r0 and r7 which is 4 * 5 turns out to equal to 14. The next problem is that for the beq rfact_done, it will go to rfact_done even though r0 != 0.
Sounds like someone has a date with a manual
 SolusIgnis (21 items) 2 Watts (6 items) Huh?! (13 items)
CPUCPUCPUMotherboard
i7-3820 Xeon Phi 31S1P Copressor (WIP) Xeon Phi 31S1P Copressor (WIP) ASRock X79 Extreme6
GraphicsRAMHard DriveCooling
XFX Reference 6950 Samsung Magic RAM Crucial M4 Cosair H80
OSMonitorMonitorMonitor
Windows 8.1 Pro HannSpree HF205 1600x900 ASUS VH239H 1920x1080 ASUS VH239H 1920x1080
CMStorm Quick Fire Pro, Cherry MX Blue Thermaltake Oversoar RX-I MadCatz RAT 9 Saitek Cyborg V.5
OtherOtherOther
Thrustmaster HOTAS Warthog TrackIR 5 Saitek Pro Combat Pedals
CPUMotherboardRAMHard Drive
Marvell PXA510 D2Plug DDR3
Optical DriveCooling
Pssh! Who needs optical drives Passive
CPUOS
i386 MS-DOS
 SolusIgnis (21 items) 2 Watts (6 items) Huh?! (13 items)
CPUCPUCPUMotherboard
i7-3820 Xeon Phi 31S1P Copressor (WIP) Xeon Phi 31S1P Copressor (WIP) ASRock X79 Extreme6
GraphicsRAMHard DriveCooling
XFX Reference 6950 Samsung Magic RAM Crucial M4 Cosair H80
OSMonitorMonitorMonitor
Windows 8.1 Pro HannSpree HF205 1600x900 ASUS VH239H 1920x1080 ASUS VH239H 1920x1080
CMStorm Quick Fire Pro, Cherry MX Blue Thermaltake Oversoar RX-I MadCatz RAT 9 Saitek Cyborg V.5
OtherOtherOther
Thrustmaster HOTAS Warthog TrackIR 5 Saitek Pro Combat Pedals
CPUMotherboardRAMHard Drive
Marvell PXA510 D2Plug DDR3
Optical DriveCooling
Pssh! Who needs optical drives Passive
CPUOS
i386 MS-DOS
I still can't figure out what is wrong with the code. I changed it to where r6 will take r0 value and multiply together and r7 will be the answer. But it just doesn't want to work for me.

From the hw05.log: Warning: Spoiler! (Click to show)
IN:
0x00000000: e3a00000 mov r0, #0 ; 0x0

R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000004
PSR=400001d3 -Z-- A svc32
IN:
0x00000004: e59f1004 ldr r1, [pc, #4] ; 0x10

R00=00000000 R01=00000183 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000008
PSR=400001d3 -Z-- A svc32
IN:
0x00000008: e59f2004 ldr r2, [pc, #4] ; 0x14

R00=00000000 R01=00000183 R02=00000100 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=0000000c
PSR=400001d3 -Z-- A svc32
IN:
0x0000000c: e59ff004 ldr pc, [pc, #4] ; 0x18

R00=00000000 R01=00000183 R02=00000100 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00010000
PSR=400001d3 -Z-- A svc32
IN:
0x00010000: e3a0d811 mov sp, #1114112 ; 0x110000

R00=00000000 R01=00000183 R02=00000100 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00110000 R14=00000000 R15=00010004
PSR=400001d3 -Z-- A svc32
IN:
0x00010004: e59f3034 ldr r3, [pc, #52] ; 0x10040

R00=00000000 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00110000 R14=00000000 R15=00010008
PSR=400001d3 -Z-- A svc32
IN:
0x00010008: e5930000 ldr r0, [r3]

R00=00000005 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00110000 R14=00000000 R15=0001000c
PSR=400001d3 -Z-- A svc32
IN:
0x0001000c: eb000000 bl 0x10014

R00=00000005 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00110000 R14=00010010 R15=00010014
PSR=400001d3 -Z-- A svc32
IN:
0x00010014: e92d4000 push {lr}

R00=00000005 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=0010fffc R14=00010010 R15=00010018
PSR=400001d3 -Z-- A svc32
IN:
0x00010018: e1a06000 mov r6, r0

R00=00000005 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000005 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=0010fffc R14=00010010 R15=0001001c
PSR=400001d3 -Z-- A svc32
IN:
0x0001001c: e2400001 sub r0, r0, #1 ; 0x1

R00=00000004 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000005 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=0010fffc R14=00010010 R15=00010020
PSR=400001d3 -Z-- A svc32
IN:
0x00010020: e0070096 mul r7, r6, r0

R00=00000004 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000005 R07=00000014
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=0010fffc R14=00010010 R15=00010024
PSR=400001d3 -Z-- A svc32
IN:
0x00010024: e3500000 cmp r0, #0 ; 0x0

R00=00000004 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000005 R07=00000014
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=0010fffc R14=00010010 R15=00010028
PSR=200001d3 --C- A svc32
IN:
0x00010028: 03a00001 moveq r0, #1 ; 0x1

R00=00000004 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000005 R07=00000014
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=0010fffc R14=00010010 R15=0001002c
PSR=200001d3 --C- A svc32
IN:
0x0001002c: 0a000000 beq 0x10034

R00=00000004 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000005 R07=00000014
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=0010fffc R14=00010010 R15=00010030
PSR=200001d3 --C- A svc32
IN:
0x00010030: ebfffff7 bl 0x10014

R00=00000004 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000005 R07=00000014
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=0010fffc R14=00010034 R15=00010014
PSR=200001d3 --C- A svc32
R00=00000001 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000001 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=0010ffec R14=00010034 R15=00010034
PSR=600001d3 -ZC- A svc32
IN:
0x00010034: e8bd4000 pop {lr}

R00=00000001 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000001 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=0010fff0 R14=00010034 R15=00010038
PSR=600001d3 -ZC- A svc32
IN:
0x00010038: e12fff1e bx lr

R00=00000001 R01=00000183 R02=00000100 R03=00010044
R04=00000000 R05=00000000 R06=00000001 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=0010fff0 R14=00010034 R15=00010034
PSR=600001d3 -ZC- A svc32

And here goes the code:
Code:
``````.global _start

_start:
MOV SP, #0X110000
LDR R3, =_tests
LDR R0, [R3]
BL RFACT
MOV R0,R7

RFACT:
PUSH {LR}
MOV R6,R0
SUB R0,R0,#1
MUL R7,R6,R0
CMP R0,#0
MOVEQ R0,#1
BEQ RFACT_DONE
BL  RFACT
RFACT_DONE:
POP {LR}
BX LR

ILOOP:
B ILOOP```
```

I don't even know what I am doing wrong any more.
Okay I got everything fixed. The 14 for the 5x4 is 20 as I didn't realize it was put into hex and what was happening was that I was multiplying with the 4 x 5 and then doing r7 * 0 = 0 since I didn't check if r0 = 0 before the multiply, then setting r0 = 1 from the moveq r0,#1.

It is also for the iteration problem to as I did the cmp before the sub which then I could just do subs r0, r0,#1 which after that, it gave me the right answer.
New Posts  All Forums:Forum Nav:
Return Home
Back to Forum: Coding and Programming
• Factorial in Arm Assembly programming
Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › Factorial in Arm Assembly programming