I have this block of code and I was wondering what address would be stored in the PC. From what I can see, it seems to be x3002 but im not quite sure.
.ORIG x3000
JSR FOO
ADD R0,R4,R2
FOO: ADD R0,R0,#1
RET
If it is not x3002 could you please let me know as to why this would be the case.
JSR will simply store into the PC the address of the label.
FOO is at x3002.
so PC will jump to x3002 and R7 will have the value x3001.
Related
I know how the 32-bit protected mode implements the jump by modifying the segment selector, but the 64-bit situation is different from what I imagined.
I wrote the descriptor in gdt.they are both same
I wrote a code segment descriptor where the selector is 0x3b, and its properties are exactly the same as the default 0x23 selector.
It fails when I access with jmp far: 0x3b: effective address.before step into after stepinto:false
But when I use jmp far 0x23:effective address it succeeds.sucess use 0x23
This question has always confused me.
My mechiane information is win7 x64.
I jumped to the address of the ring3 program segment, which is a legal address.
My question is why is this failing? There is no problem doing this on XP-32, why does win764 fail. How to jump correctly.
In Go assembly on arm64, I have created a table of values
DATA table<>+0(SB)/4, 0x00000001
DATA table<>+4(SB)/4, 0x00000002
DATA table<>+8(SB)/4, 0x00000003
DATA table<>+12(SB)/4, 0x00000004
But what I want to be able to do is load up a value into a register from this table, but based on a variable.
If I had a constant I could do
MOVD table<>+4(SB), R1
so R1=0x00000002
but how can I do it with a variable? Something like...
MOVD $4, R0
MOVD table<>+R0(SB), R1
Or better yet, can I get the address and load a vector directly?
I guess the answer in normal are is ADR, but when I try that in go
ADR table<>(SB), R0
I just get
asm: illegal combination: 00280 [...] ADR table<>(SB), R9 ADDR NONE NONE REG, 3 7
Which is maybe the least useful error message I've ever seen.
Okay, so ADR works if I do PC relative addressing, but that's obviously not right.
Turns out it's really easy, you just put a $ before the variable
MOVD $table<>+0(SB), R0
I've got a program that I'm running on an ARM and I'm writing one function of it in assembly. I've made good progress on this, although I've found it difficult sometimes to figure out exactly how to write certain instructions for go's assembler, for example, I didn't expect a right shift to be written like this:
MOVW R3>>8, R3
Now I want to do a multiply and accumulate (MLA), according to this doc not all opcodes are supported, so maybe MLA isn't, but I don't know how to tell if it is or not. I see mentions of MLA with regards to ARM in the golang repo, but I'm not really sure what to make of what I see there.
Is there anywhere that documents what instructions are supported and how to write them? Can anyone give me any useful pointers?
Here is a bit of a scrappy doc i wrote on how to write ARM assembler
I wrote it from the point of view of an experienced ARM person trying to figure out how Go assembler works.
Here is an excerpt from the start. Feel free to email me if you have more questions!
The Go assembler is based on the plan 9 assembler which is documented here.
http://plan9.bell-labs.com/sys/doc/asm.html
Nice introduction to ARM
http://www.davespace.co.uk/arm/introduction-to-arm/index.html
Opcodes
http://simplemachines.it/doc/arm_inst.pdf
Instructions
Destination goes last not first
Parameters seem to be completely reversed
May be condensed to 2 operands, so
ADD r0, r0, r1 ; [ARM] r0 <- r0 + r1
is written as
ADD r1, r0, r0
or
ADD r1, r0
Constants denoted with '$' not '#'
I'm trying to write a firmware mod (to existing firmware, for which i don't have source code)
All Thumb code.
does anybody have any idea how to do this, in gcc as (GAS) assembler:
Use BL without having to manually calculate offsets, when BL'ing to some existing function (not in my code.. but i know its address)
Currently, if i want to use BL ...i have to :
-go back in my code
-figure out and add all the bytes that would result from assembling all the previous instructions in the function i'm writing
-add the begining address of my function to that (i specify the starting address of what i'm writing, in the linker script)
-and then substract the address of the firmfunc function i want to call
All this... just to calculate the offset... to be able to write abl offset... to call an existing firmware function?
And if i change any code before that BL, i have to do it all over again manually !
See.. this is why i want to learn to use BX right... instead of BL
Also, i don't quite understand the BX. If i use BX to jump to an absolute address, do i have to increase the actual address by 1, when caling Thumb code from Thumb code (to keep the lsb byte 1)... and the CPU will know it's thumb code ?
BIG EDIT:
Changing the answer based on what I have learned recently and a better understanding of the question
First off I dont know how to tell the linker to generate a bl to an address that is a hardcoded address and not actually in this code. You might try to rig up an elf file that has labels and such but dummy or no code, dont know if that will fool the linker or not. You would have to modify the linker script as well. not worth it.
your other question that was spawned from this one:
Arm/Thumb: using BX in Thumb code, to call a Thumb function, or to jump to a Thumb instruction in another function
For branching this works just fine:
LDR R6, =0x24000
ADD R6, #1 # (set lsb to 1)
BX R6
or save an instruction and just do this
LDR R6, =0x24001
BX R6
if you want to branch link and you know the address and you are in thumb mode and want to get to thumb code then
ldr r6,=0x24001
bl thumb_trampoline
;#returns here
...
.thumb_func
thumb_trampoline:
bx r6
And almost the exact same if you are starting in arm mode, and want to get to thumb code at an address you already know.
ldr r6,=0x24001
bl arm_trampoline
;#returns here
...
arm_trampoline:
bx r6
You have to know that you can trash r6 in this way (make sure r6 isnt saving some value being used by some code that called this code).
Very sorry misleading you with the other answer, I could swear that mov lr,pc pulled in the lsbit as a mode, but it doesnt.
The accepted answer achieves the desired goal, but to address the answer exactly as asked you can use the .equ directive to associate a constant vale with a symbol, that can then be used as an operand to instructions. This has the assembler synthesise the trampoline if/when necessary:
equ myFirmwareFunction, 0x12346570
.globl _start
mov r0, #42
b myFirmwareFunction
Which generates the following assembly[1]
01000000 <_start>:
1000000: e3a0002a mov r0, #42 ; 0x2a
1000004: eaffffff b 1000008 <__*ABS*0x12346570_veneer>
01000008 <__*ABS*0x12346570_veneer>:
__*ABS*0x12346570_veneer():
1000008: e51ff004 ldr pc, [pc, #-4] ; 100000c <__*ABS*0x12346570_veneer+0x4>
100000c: 12346570 data: #0x12345670
If the immediate value is close enough to PC that the offset will fit in the immediate field, then the verneer (trampoline) is skipped and you will get a single branch instruction to the specified constant address.
[1] using the codesorcery (2009q1) toolchain with:
arm-none-eabi-gcc -march=armv7-a -x assembler test.spp -o test.elf -Ttext=0x1000000 -nostdlib
I'm currently reading a tutorial on Raspberry Pi OS development and was wondering about the way local labels are used in this code snippet (GCC ARM Assembly):
...
b 2f
1:
stmia r4!, {r5-r8}
2:
cmp r4, r9
blo 1b
...
If you use 1: as a label you have to specify either f or b after the jump instruction to make the assembler know in which direction the jump is aimed. As far as I know you could also use this:
...
b .2
.1:
stmia r4!, {r5-r8}
.2:
cmp r4, r9
blo .1
...
I think this option is a lot less confusing (local labels are also marked with a dot in x86 assembly), because there is no additional letter after the label reference. I have tested the resulting machine code and it's the same. So my questions:
Why would you use the one variant over the other?
Why is it necessary to specify the direction of the jump with either f or b?
The important difference is that the numbered local labels can be reused without worry and that is why you need to specify the direction too. You can jump to preceding or following one, but not the ones beyond them.
1: foo
...
1: bar
...
jmp 1b # jumps to bar
...
jmp 1f # jumps to baz
...
1: baz
...
1: qux
...
jmp 1b # jumps to qux
As long as you only use them within a single block only, you can be sure they will work as intended and not conflict with anything else.
One of the main benefits of local labels is that since the same identifier can appear multiple times, they can be used in macros. Consider some hypothetical local label usage like this, though:
.macro dothething rega regb ptr
ldrex \regb, [\ptr]
cmp \rega, \regb
beq 1
2: <more instructions>
...
strex \regb, \rega, [ptr]
cmp \regb, #0
bne 2
1:
.endm
myfunction:
dothething r0 r1 r2
dothething r0 r1 r3
bx lr
That's actually allowed in armasm (albeit with slightly different syntax), where the behaviour in the absence of a specified direction is "search backwards, then forwards", but still under any reasonable default behaviour at least one of the jumps in the above code is going to end up targeting the wrong instance of a label. Explicitly calling out the direction with beq 1f and bne 2b in the macro resolves the ambiguity and generates the right jumps in both invocations of the macro.
If you choose to use something that isn't a true local label, then not only do you potentially clutter up your symbol table with junk, but you also rob yourself of being able to use loops or conditional branching in macros since you'd generate non-unique symbols. My example might seem a bit contrived, but switch from assembler macros to inline asm blocks in C functions which get inlined all over your complex codebase, and things get a lot more real.