sub-routines on Assembly - c

can I do something like this on Assembly bne jsr swap, if not how can I solve this problem from C, thanks in advance
if(start!=pivot_index){
swap(board,start,pivot_index);
}
I was taught that I must write jsr and sub-routine but can I do something like this bne sub-routine

In assembly that would usually be translated into something like this (pseudo-assembly):
load [start]
compare [pivot_index]
branch-if-equal label1
push [pivot_index]
push [start]
push [board]
call swap
add-stack-pointer 12
label1:
ie. the if statement is converted into a jump that jumps over the body of the if if the controlling expression is not true.

Sure you can do this. On x86 you need two branches:
# assume EAX = start, EBX = pivot_index
cmp eax, ebx
beq .SkipSwap
call swap
.SkipSwap:
For ARM assembly it's easier because you can use a conditional branch:
# assume r0 = start, r1 = pivot_index
cmp r0, r1
blne swap

No, you cannot do bne subroutine instead of jsr subroutine, because jsr means "jump setting return".
The difference between that and the conditional branch instructions is that the jsr pushes the return address onto the stack, so the subroutine knows where to return. If you just branch to the subroutine using bne, there's no return address saved, so the subroutine doesn't know where to return when done.
caf's answer shows you the typical way you would handle that, you just need to translate it into PDP-11 operations.

Related

Assembly language x86 IRVINE infinite loops

I'm new to Assembly language and I need help with an error I keep experiencing, my task in class is to do what I did below, everything I did is correct and how the professor wants it but I can't stop the program from infinite looping, I have the correct answer which is 14 but how do I stop the loop from being infinite without using special commands like ret. How do I stop it?
;Declare an array of words
;Write a loop that adds all the elements of the array located in even places
;Example 3,7,2,8,9
;3+2+9=14
INCLUDE Irvine32.inc
.data
val1 WORD 3,7,2,8,9
.code
main PROC
mov eax, 0
L1:
mov ecx, (LENGTHOF val1)*(TYPE val1+2)-(TYPE val1+4)
mov eax, ecx
call writeDec
loop L1
exit
main ENDP
END main
At the bottom of your loop, you have this instruction:
loop L1
which means "go back to L1."
Loop L1 is a conditional LOOP that is based on the value in ECX. The
real issue is the problem with the value in ECX. LOOP will first
decrement ECX by 1 and compare the new value in ECX with zero. If it
isn't zero it goes to the label (L1). If it is zero it falls through.
Look carefully at where you set the value of ecx. After LOOP decrements ecx by 1 and execution goes to L1, what happens?

PE File Injection

I have some problem with my project. I want insert my code in any program. I explain the situatuion: My program take file (PE type) and start XOR'ed data from First Section to Last Section. Then I download in last section my ASM code, which decodes this data. I marked Last Section like (Write, Execute, Data). My ASM Code:
mov eax, /*I insert address of the beginning of the first section*/
mov ebx, /* I insert orginal EntryPoint (need to use jmp in the end)*/
mov cx, /*I insert number of bytes between Last Section and First*/
DO:
mov ch, [eax]
xor ch,2
mov [eax], ch
inc eax
loop DO
jmp ebx
I repaired VirtualSize, SizeOfRawData (add 24 to everyone + made alignment). Also I changed SizeOfImage and BaseOfCode (here I wrote new address my asm code (pLastSectHeader->Misc.VirtualSize)).
But I have problem when I run my app (which I injected). Help me please with my problem :) I trying make this few weeks.
P.S My code on Plain C + WinAPI http://pastebin.com/Q4EJvM2J
ch is part of ecx so you are overwriting your counter. Also, x86 allows xor with memory operand, so just do xor byte [eax], 2. Furthemore, you should load ecx not just cx because loop uses all of ecx.
Note that if the sections you are trying to decrypt are not marked writable, you are going to run into problems there too.
Learn to use a debugger and next time provide better question than "I have problem when I run my app".

SPARC Assembly, setting the C flag

The is leaving me baffled, and I really can't figure out why I am getting this problem. I am to create a program in c that outputs an unsigned value just before the C flag is set, using assembly to accumulate a variable with addcc, and send back the value to main in c. I believe the code I have for c is correct:
unsigned int func();
int main(void){
printf("The max value before the C flag is set is: %u\n", func());
}
Now the problem comes in with the assembly...
.global func
func: save %sp, -128, %sp
addcc %g0, 1, %g0
clr %l0
loop:
bcs away
mov %l0, %i0
addcc %i0, 1, %l0
ba loop
nop
away:
ret
restore
What this should be doing is accumulating %l0, when the C flag is set passing the value back to %i0 and returning it. When I run this, I get 0. This doen's make sense to me, as I believe I should be getting a much larger number. Any help would be appreciated.
The problem is that branches on Sparc are delayed -- the next instruction after the branch will be executed before the branch actually executes. So when you have:
bcs away
mov %l0, %i0
when the C flag is set and this branch is taken, the mov will still execute, overwriting the value in %i0 (the value before the last add that set C) with %l0 (the value after the add -- 0).
If you stick a nop in here:
bcs away
nop
mov %l0, %i0
it should give you the value you want.

8086 assembly - how to access array elements within a loop

Ok, to make things as simple as possible, say I have a basic loop that i want to use in order to modify some elements of an array labeled a. In the following sample code I've tried replacing all elements of a with 1, but that doesn't really work.
assume cs:code ,ds:data
data segment
a db 1,2,3,4
i db 0
data ends
code segment
start:
mov ax,data
mov ds,ax
lea si,a
the_loop:
mov cl,i
cmp cl,4
jae the_end
mov ds:si[i],1 ; this is the part that i don't really understand since
inc i ; i'm expecting i=0 and ds:si[i] equiv to ds:si[0] which
loop the_loop ; is apparently not the case here since i actually receives the
; the value 1
the_end:
mov ax,4c00h
int 21h
code ends
end start
I am aware that I could simply do this by modifying the element stored in al after the lodsb instruction, and just store that. But I would like to know if it is possible to do something like what I've tried above.
In x86 assembly you can't use a value stored to a memory to address memory indirectly.
You need to read i into some register that can be used for memory addressing, and use that instead. You may want to check Wikipedia for 8086 memory addressing modes.
So, replace
mov ds:si[i],1
with (segment ds is unnecessary here, as it's the default of si, bx and bx+si too):
xor bx,bx
mov bl,[i]
mov [bx+si],byte 1 ; some other assemblers want byte ptr
There are other problems with your code too. The entire loop can be made easier and fixed this way:
lea si,a
xor cx,cx
mov cl,[i]
#fill_loop:
mov [si], byte 1
inc si
dec cx
jnz #fill_loop
Or, if you want to save 1 byte and use loop instruction.
#fill_loop:
mov [si], byte 1
inc si
loop #fill_loop
Note that in 16-bit mode loop instruction decrements cx and jumps to label if cx is not zero after decrement. However, in 32-bit mode loop decrements ecx and in 64-bit mode (x86-64) it decrements rcx.
I suppose that your code does not even run through the assembler, since
mov ds:si[i],1
is not a valid address mode.
Use something like
mov byte ptr [si],1 ; store value 1 at [SI]
inc si ; point to next array element
instead (used MASM to verify the syntax).
The DS: prefix is unnecessary for [si] since this is the default.
See also The 80x86 Addressing Modes.

cmp je/jg how they work in assembly

I would like to understand how cmp and je/jg work in assembly. I saw few examples on google but I am still little bit confused. Below I have shown a part of assembly code that I am trying to convert to C language and the corresponding C code. Is it implemented in the right way or do I have a wrong understanding of how cmp works?
cmp $0x3,%eax
je A
cmp $0x3,%eax
jg B
cmp $0x1,%eax
je C
int func(int x){
if(x == 3)
goto A;
if (x >3)
goto B;
if(x == 1)
goto C;
A:
......
B:
......
C:
......
You understand correctly how cmp and je/jg work, but you have an error in your C code. This line:
if (*x == 1)
should be
if (x == 1)
Here is a pretty good summary of the x86 control flow instructions.
Also, there's no reason to repeat the cmp instruction for the same values. Once you've executed it, you can test the results multiple ways without repeating the comparison. So your assembly code should look like this:
cmp $0x3,%eax
je A
jg B
cmp $0x1,%eax
je C
Yes, that's correct, except that in your C code you have *x in third example but x in others, that does not make sense. In your assembly code there is no correspoding code.
In C the variable type (signed/unsigned) is defined upon declaring the variable, eg. int x or unsigned int x, but in assembly the distinction between signed and unsigned variables (be they in memory or in registers) for comparisons is made by different conditional jumps:
For signed variables:
jg ; jump if greater
jl ; jump if less
jge ; jump if greater or equal, "jnl" is synonymous
jle ; jump if less or equal, "jng" is synonymous
For unsigned variables:
ja ; jump if above
jb ; jump if below
jae ; jump if above or equal, "jnb" is synonymous
jbe ; jump if below or equal, "jna" is synonymous
Intel x86 JUMP quick reference lists all conditional jumps available in x86 assembly, together with their conditions (flags' values) and their opcodes for short and long jumps.
As you may already know, the processor keeps track of the stuff that happened during last operations in a so-called flags-register.
For example, there is a flag if an operation made an overflow, or the result was zero etc. The cmp mnemonic tells the processor to subtract the two registers/ register and memory content and it changes the correct flags.
After that, you can jump using the jumps you have done. The processor checks the flags to see if it was equal-je, (checks the zero flag), or if it was smaller/bigger(overflow flag for unsigned and overflow and sign flag for signed numbers).

Resources