ABI call to __aeabi_idivmod doesn't behave as expected - arm

I'm trying to develop a program on a bare metal architecture (stm32f4 board with ARM cortex-m4f processor). I'm experiencing a strange problem with the ABI call __aebi_idivmod.
The call is generated by the compiler because in the code there is multiple use of the % operand.The strange thing is that if I look at the dump of the .elf generated by the compilation using objdump, what I get is:
080080e0 <__aeabi_idivmod>:
80080e0: e3510000 cmp r1, #0
80080e4: 0afffff9 beq 80080d0 <.divsi3_skip_div0_test+0x110>
80080e8: e92d4003 push {r0, r1, lr}
80080ec: ebffffb3 bl 8007fc0 <.divsi3_skip_div0_test>
80080f0: e8bd4006 pop {r1, r2, lr}
80080f4: e0030092 mul r3, r2, r0
80080f8: e0411003 sub r1, r1, r3
80080fc: e12fff1e bx lr
On the other hand when I run the program on the board, if I look at the actual ABI call code using gdb I get:
(gdb) disas __aeabi_idivmod
Dump of assembler code for function __aeabi_idivmod:
0x080080e0 <+0>: movs r0, r0
0x080080e2 <+2>: b.n 0x8008788
0x080080e4 <+4>: ; <UNDEFINED> instruction: 0xfff90aff
0x080080e8 <+8>: ands r3, r0
0x080080ea <+10>: stmdb sp!, {r0, r1, r4, r5, r7, r8, r9, r10, r11, r12, sp, lr, pc}
0x080080ee <+14>: ; <UNDEFINED> instruction: 0xebff4006
0x080080f2 <+18>: ldmia.w sp!, {r1, r4, r7}
0x080080f6 <+22>: b.n 0x8008100 <__aeabi_ldiv0>
0x080080f8 <+24>: asrs r3, r0, #32
0x080080fa <+26>: b.n 0x8008180 <K+120>
0x080080fc <+28>: vrhadd.u16 d14, d14, d31
End of assembler dump.
The location of the code corresponds, but it is completely wrong: there are two instructions that are not even recognized by gdb and the second instruction:
0x080080e2 <+2>: b.n 0x8008788
is jumping outside of the .text section of the process that ends at 0x866c:
Loading section .text, size 0x866c lma 0x8000000
Any clue about I'm doing wrong? Any help would be appreciated.
EDIT: I'm using this compiler: https://launchpad.net/gcc-arm-embedded/+download
arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.8.3 20131129 (release) [ARM/embedded-4_8-branch revision 205641]
EDIT2 (following the response of Notlikethat): The command that I use to link my program is this:
$(ARMGNU)-ld -o program.gcc.thumb.elf -T memmap vectors.o program.gcc.thumb.o $(OBJS2) $(LIBGCC)
memmap is the linker script, vectors.o contains startup code, $(OBJS2) contains all the object files that must be linked together and $(LIBGCC) is the variable referencing the library containing the ABI call that we're discussing. From what I've understood from the comment of Notlikethat I should add some option here, to force the compilation of the libgcc to thumb code instead of normale ARM code. I've tried to add to the linker these options, but I'm getting the same error in both cases:
arm-none-eabi-ld: unrecognised emulation mode: cpu=cortex-m3
Supported emulations: armelf
EDIT3: I have realized only in this moment that the processor of my board is cortex-m4f not cortex-m3. I don't think this should not make much different.

The problem is that your toolchain, by default, has its standard library compiled to ARM instructions - since the Cortex-M processors only support Thumb-2*, they will fault when attempting to use an interworking branch to ARM code.
Now, the -mthumb option tells the compiler to compile your code to Thumb - the standard library is pre-compiled and doesn't even come into the picture until link time. Fortunately, the readme says that toolchain is multilib enabled, so you can pick a suitable library without having to find a v7-M-specific toolchain.
From what I understand of the inner workings of multilib, you have to provide the exact magic combination of options it's looking for, which in this case would be either:
-mthumb -mcpu=cortex-m4
or:
-mthumb -march=armv7e-m
which will cause GCC to give the linker a suitably compatible library instead of the default (there are further options listed in the docs if you need floating-point support too).
If you're using a seperate link step, I believe you need to use gcc as the link command in place of ld for multilib to work correctly - that's certainly the case for the Linaro toolchain I have here (which only has two-way hard-float/ARMv4+soft-float multilib).
* strictly, not-quite-all-of-Thumb-2

Related

How to load binary to DRAM with JLink JTAG to debug?

I am doing a ARM+RTOS project, and I want to download the binary to target board with JLink JTAG.
But every time 'loadbin a.bin 0x40000000' will report error -1, and says 'failed to read memory', 0x40000000 is the starting address of DRAM.
I have to use 'r' command to reset JTAG port to read memory back.
The JLINK driver is 6.72 installed in Ubuntu-20.04.5, the ARM is an allwinner chip (cortex-a7).
I am wondering how to download the binary image into DRAM thru JLink JTAG to debug.
Updated with more details.
The board is based on sun8i, with 2 ARMv7 cores.
The JLink can identify the JTAG adapter as follows,
Connecting to target via JTAG
ConfigTargetSettings() start
Setting up: AW Cortex-A7
ConfigTargetSettings() end
TotalIRLen = 4, IRPrint = 0x01
JTAG chain detection found 1 devices:
#0 Id: 0x5BA00477, IRLen: 04, CoreSight JTAG-DP
AP map detection skipped. Manually configured AP map found.
AP[0]: AHB-AP (IDR: Not set)
AP[1]: APB-AP (IDR: Not set)
Using preconfigured AP[1] as APB-AP
AP[1]: APB-AP found
ROMTbl[0][0]: CompAddr: 80050000 CID: B105900D, PID:04-004BB906 CTI
ROMTbl[0][1]: CompAddr: 81000000 CID: B105100D, PID:08-00A9CC32 ROM Table
ROMTbl[1][0]: CompAddr: 81010000 CID: 00000000, PID:00-00000000 ???
ROMTbl[1][1]: CompAddr: 81020000 CID: 00000000, PID:00-00000000 ???
ROMTbl[1][2]: CompAddr: 81400000 CID: B105100D, PID:04-000BB4A7 ROM Table
ROMTbl[2][0]: CompAddr: 81410000 CID: B105900D, PID:04-005BBC07 Cortex-A7
Found Cortex-A7 r0p5
6 code breakpoints, 4 data breakpoints
Debug architecture ARMv7.1
Data endian: little
Main ID register: 0x410FC075
I-Cache L1: 32 KB, 512 Sets, 32 Bytes/Line, 2-Way
D-Cache L1: 32 KB, 128 Sets, 64 Bytes/Line, 4-Way
Unified-Cache L2: 256 KB, 512 Sets, 64 Bytes/Line, 8-Way
System control register:
Instruction endian: little
Level-1 instruction cache enabled
Level-1 data cache enabled
MMU enabled
Branch prediction enabled
Memory zones:
[0]: Default (Default access mode)
[1]: AHB-AP (AP0) (DMA like acc. in AP0 addr. space)
[2]: APB-AP (AP1) (DMA like acc. in AP1 addr. space)
Cortex-A7 identified.
The JLinkGDBServer and gdb can attach and debug the code running (burned with a tool in Windows) in RAM, such as reading memory, modify memory etc.
But the gdb command of load a.elf will fail with error in memory writing.
And the loadbin a.bin 0x40000000 in JLinkExe also failed with memory writing.
with steps of loading add.c from Frant in my system
The JLinkGDBServer is running in another xterm, and run gdb-multiarch
(gdb) monitor reset
Resetting target
(gdb) x/8x 0x40000000
0x40000000: 0xea00001e 0x736f7472 0x00000000 0xa143480d
0x40000010: 0x0008b630 0x0008b630 0x0008b630 0x2e302e30
(gdb) load add.elf
`/home/t/develop/ctest/add.elf' has changed; re-reading symbols.
(no debugging symbols found)
Loading section .note.gnu.build-id, size 0x24 lma 0x100b4
Loading section .text, size 0x64 lma 0x40000000
Start address 0x40000000, load size 136
Transfer rate: 5 KB/sec, 68 bytes/write.
(gdb) x/8x 0x40000000
0x40000000 <main>: Cannot access memory at address 0x40000000
Before loading elf to DRAM, memory at 0x40000000 (start of DRAM) can be read from GDB. But after loading elf, that memory cannot be read from GDB.
The JLinkGDBServer also reported...
Downloading 36 bytes # address 0x000100B4
Downloading 100 bytes # address 0x40000000
Writing register (PC = 0x40000000)
Reading all registers
WARNING: Failed to read memory # address 0x40000000
Then, I changed to use JLinkExe to load a binary file of 4KB (all 0s) as follows,
J-Link>r
Reset delay: 0 ms
Reset type NORMAL: Toggle reset pin and halt CPU core.
J-Link>mem32 0x40000000 16
40000000 = EA00001E 736F7472 00000000 A143480D
40000010 = 0008B630 0008B630 0008B630 2E302E30
40000020 = 00000030 2E302E30 00000030 40000000
40000030 = 00000000 00000000 00000000 00000000
40000040 = 00000000 00000000 00000000 00000000
40000050 = 00000040 00000000
J-Link>loadbin zero.bin 0x40000000
Downloading file [zero.bin]...
Unspecified error -1
J-Link>
Tried with sunxi-fel tool
(base):~/tools/sunxi-tools-master$ sudo ./sunxi-fel -v --list
USB device 001:035 Allwinner R528 93406400:0c004814:0146880a:044713cd
(base):~/tools/sunxi-tools-master$ sudo ./sunxi-fel -p write 0x40000000 ~/u-boot.bin
usb_bulk_send() ERROR -7: Operation timed out
(base):~/tools/sunxi-tools-master$ sudo ./sunxi-fel -v --list
usb_bulk_send() ERROR -7: Operation timed out
Firstly, sunxi-fel can detect and list the attached device.
Then to load u-boot.bin to DRAM hit an error (Maybe from DRAM not initialized).
Last, the sunxi-fel cannot detect and list the attached device, I have to power cycle the board to bring it back.
This is not clear from your original question what the state of your device is prior to your attempt, nor what exact model of SBC you are using.
However, here are two different approaches you could probably use for achieving your goal. Ubuntu 22.04, Jlink software V7.84c, a JLink EDU and a FriendlyElec nanopi-2 neo with an Allwinner H3 were used for the purpose of this answer.
They could probably be adapted to a different 32 bit Alwinner SoC having JTAG support, and an SBC having the JTAG signals properly wired.
It worked for me using a nanopi2-m1 and an orangepi-zero.
You have two issues to solve here prior to be able to upload your binary usin g the JLink probe:
Making sure the SDRAM controller is configured so that the SDRAM will be readable/writable,
Enable the JTAG on some PIO port supporting the JTAG functionality: for example, the reset value for the H3 PA Configure Register is 0x77777777, that is the JAG functionality is not enable at reset. As a side-effect, if you are resetting the SoC using the JLink probe, you will lose the JTAG connectivity.
Approach #1 - using u-boot
In this case, the u-boot SPL will obviously already have configured the SDRAM controller, and its content will be usable, and you will just have to enable the JTAG functionality on PIO port A.
You will need to write the value 0x77223333 into the PA Configure Register at address 0x01c20800 in order to enable the JTAG functionality on PIO port A- please refer to 4.22.1. Port Controller Register List and 4.22.2. Port Controller Register Description of the Allwinner H3 Datasheet.
U-Boot SPL 2023.01 (Jan 24 2023 - 15:18:15 -0500)
DRAM: 512 MiB
Trying to boot from MMC1
U-Boot 2023.01 (Jan 24 2023 - 15:18:15 -0500) Allwinner Technology
CPU: Allwinner H3 (SUN8I 1680)
Model: FriendlyARM NanoPi NEO
DRAM: 512 MiB
Core: 60 devices, 17 uclasses, devicetree: separate
WDT: Not starting watchdog#1c20ca0
MMC: mmc#1c0f000: 0
Loading Environment from FAT... OK
In: serial
Out: serial
Err: serial
Net: eth0: ethernet#1c30000
starting USB...
Bus usb#1c1a000: probe failed, error -2
Bus usb#1c1a400: probe failed, error -2
Bus usb#1c1d000: USB EHCI 1.00
Bus usb#1c1d400: USB OHCI 1.0
scanning bus usb#1c1d000 for devices... 1 USB Device(s) found
scanning bus usb#1c1d400 for devices... 1 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
=>
Enabling JTAG on PA:
mw.l 0x01c20800 0x77223333 1
=>
Starting the JLink GDD server - Ubuntu system:
<!-- language-all: lang-text -->
/opt/jlink$/opt/JLink_Linux_V784c_x86_64/JLinkGDBServerCLExe -select USB -device Cortex-A7 -endian little -if JTAG -speed 4000 -noir -noLocalhostOnly -nologtofile -port 2331 -SWOPort 2332 -TelnetPort 2333
SEGGER J-Link GDB Server V7.84c Command Line Version
JLinkARM.dll V7.84c (DLL compiled Jan 20 2023 12:25:58)
Command line: -select USB -device Cortex-A7 -endian little -if JTAG -speed 4000 -noir -noLocalhostOnly -nologtofile -port 2331 -SWOPort 2332 -TelnetPort 2333
-----GDB Server start settings-----
GDBInit file: none
GDB Server Listening port: 2331
SWO raw output listening port: 2332
Terminal I/O port: 2333
Accept remote connection: yes
Generate logfile: off
Verify download: off
Init regs on start: off
Silent mode: off
Single run mode: off
Target connection timeout: 0 ms
------J-Link related settings------
J-Link Host interface: USB
J-Link script: none
J-Link settings file: none
------Target related settings------
Target device: Cortex-A7
Target device parameters: none
Target interface: JTAG
Target interface speed: 4000kHz
Target endian: little
Connecting to J-Link...
J-Link is connected.
Firmware: J-Link ARM V8 compiled Nov 28 2014 13:44:46
Hardware: V8.00
S/N: ********
OEM: SEGGER-EDU
Feature(s): FlashBP, GDB
Checking target voltage...
Target voltage: 3.31 V
Listening on TCP/IP port 2331
Connecting to target...
J-Link found 1 JTAG device, Total IRLen = 4
JTAG ID: 0x5BA00477 (Cortex-A7)
Connected to target
Waiting for GDB connection...
At this stage, the JLink GDB server successfully connected the H3 using the JTAG interface.
We now need a small example program - add.c
int main(int argc, char** argv) {
const int count = 5;
int result = 0;
for (int i = 1; i < count; i++) {
result = result + i;
}
done:
// We should rather use 'WFI' here.
goto done;
}
Compiling add.elf:
/opt/arm/10/gcc-arm-10.3-2021.07-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -O0 -nostdlib -nostartfiles -e main -Wl,-Ttext=0x0000000042000000 -o add.elf add.c
/opt/arm/10/gcc-arm-10.3-2021.07-x86_64-arm-none-eabi/bin/arm-none-eabi-objdump -D -j .text add.elf > add.lst
cat add.lst
add.elf: file format elf32-littlearm
Disassembly of section .text:
42000000 <main>:
42000000: e52db004 push {fp} ; (str fp, [sp, #-4]!)
42000004: e28db000 add fp, sp, #0
42000008: e24dd01c sub sp, sp, #28
4200000c: e50b0018 str r0, [fp, #-24] ; 0xffffffe8
42000010: e50b101c str r1, [fp, #-28] ; 0xffffffe4
42000014: e3a03005 mov r3, #5
42000018: e50b3010 str r3, [fp, #-16]
4200001c: e3a03000 mov r3, #0
42000020: e50b3008 str r3, [fp, #-8]
42000024: e3a03001 mov r3, #1
42000028: e50b300c str r3, [fp, #-12]
4200002c: ea000006 b 4200004c <main+0x4c>
42000030: e51b2008 ldr r2, [fp, #-8]
42000034: e51b300c ldr r3, [fp, #-12]
42000038: e0823003 add r3, r2, r3
4200003c: e50b3008 str r3, [fp, #-8]
42000040: e51b300c ldr r3, [fp, #-12]
42000044: e2833001 add r3, r3, #1
42000048: e50b300c str r3, [fp, #-12]
4200004c: e51b200c ldr r2, [fp, #-12]
42000050: e51b3010 ldr r3, [fp, #-16]
42000054: e1520003 cmp r2, r3
42000058: bafffff4 blt 42000030 <main+0x30>
4200005c: e1a00000 nop ; (mov r0, r0)
42000060: eafffffe b 42000060 <main+0x60>
Starting a GDB session and loading add.elf:
/opt/gdb/gdb-12.1-arm-none-eabi-x86_64-linux-gnu/bin/arm-none-eabi-gdb
GNU gdb (GDB) 12.1
Copyright (C) 2022 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 "--host=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) target remote localhost:2331
Remote debugging using localhost:2331
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x42000004 in ?? ()
(gdb) load add.elf
Loading section .text, size 0x64 lma 0x42000000
Start address 0x42000000, load size 100
Transfer rate: 32 KB/sec, 100 bytes/write.
(gdb) b *0x42000000
Breakpoint 1 at 0x42000000
At this stage, the program was load into the nanipo2-neo,and a break-point
was set at 0x42000000.
By switching to the TUI mode, we can step trough the program using the stepi command:
Approach #2 - using FEL mode and sunxi-fel
With this approach, you would boot your SBC in FEL mode, configure the SDRAM controller using the following command: sunxi-fel spl u-boot-sunxi-with-spl.bin, as explained on the FEL/USBBoot page of the linux-sunxi WEB site.
Enabling the JTAG functionality could than be done using the following command: sunxi-fel writel 0x01c20800 0x77223333.
Starting the JLink GDB server and launching a GDB debug session could then be done as described above.
After upgraded to JLink ver.7.0.0,the image downloading and debugging in DRAM are working well as expected.

I'd like to link malloc/realloc/free without having a lib file

If you look at my recent post history I went from hello world assembly to building it on linux and running on mac.
I didn't see an obvious way to implement realloc efficiently. So I'm looking into if I can link it. The issue is I'm not sure if I'm allowed to distribute mac files so I don't think I can distribute a lib file (unless I can build one myself?)
Below is my c code, that's all I'm interested in linking for the moment.
#include <stdlib.h>
int main() {
free(realloc(malloc(1024*10), 1024*100));
}
I see a stubs section in objdump
0000000100003f94 <__TEXT.__stubs>:
100003f94: b0000010 adrp x16, 100004000 <_main+0x98>
100003f98: f9400210 ldr x16, [x16]
100003f9c: d61f0200 br x16
100003fa0: b0000010 adrp x16, 100004000 <_main+0x98>
100003fa4: f9400610 ldr x16, [x16, #8]
100003fa8: d61f0200 br x16
100003fac: b0000010 adrp x16, 100004000 <_main+0x98>
100003fb0: f9400a10 ldr x16, [x16, #16]
100003fb4: d61f0200 br x16
Section:
3 __DATA_CONST.__got 00000018 0000000100004000 0000000100004000 00004000 2**3
CONTENTS, ALLOC, LOAD, DATA
I'm not sure how to put all of this together in order to link without requiring my team to copy mac specific libs to their system (and I'm sure I'm not allowed to distribute it?). Is there a way I can build a lib that I can distribute and use to cross compile?

Aarch64 baremetal Hello World program on QEMU

I have compiled and ran a simple hello world program on ARM Foundation Platform. The code is given below.
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello world!\n");
return 0;
}
This program is compiled and linked using ARM GNU tool chain as given below.
$aarch64-none-elf-gcc -c -march=armv8-a -g hello.c hello.o
aarch64-none-elf-gcc: warning: hello.o: linker input file unused because linking not done
$aarch64-none-elf-gcc -specs=aem-ve.specs -Wl,-Map=linkmap.txt hello.o -o hello.axf
I could successfully execute this program on ARM Foundation Platform (I think, foundation platform is similar to ARM Fixed Virtual Platform) and it prints "Hello world!"
The contents of 'aem-ve.specs' file is given below:
cat ./aarch64-none-elf/lib/aem-ve.specs
# aem-ve.specs
#
# Spec file for AArch64 baremetal newlib, libgloss on VE platform with version 2
# of AngelAPI semi-hosting.
#
# This Spec file is also appropriate for the foundation model.
%rename link old_link
*link:
-Ttext-segment 0x80000000 %(old_link)
%rename lib libc
*libgloss:
-lrdimon
*lib:
cpu-init/rdimon-aem-el3.o%s --start-group %(libc) %(libgloss) --end-group
*startfile:
crti%O%s crtbegin%O%s %{!pg:rdimon-crt0%O%s} %{pg:rdimon-crt0%O%s}
Is it possible to execute the same binary on QEMU? If so could you please share the sample command. If not, could you please share the right and best way to execute it on QEMU?
I have traced instruction execution of Foundation platform using the "trace" option and analysed using 'tarmac-profile' tool and 'Tarmac-calltree' tool. The outputs are given below:
$ ./tarmac-profile hello.trace --image hello.axf
Address Count Time Function name
0x80000000 1 120001
0x80001030 1 30001 register_fini
0x80001050 1 60001 deregister_tm_clones
0x800010c0 1 210001 __do_global_dtors_aux
0x80001148 1 23500001 frame_dummy
0x800012c0 1 10480001 main
0x80002000 1 40001 main
0x80003784 1 360001 main
0x80003818 1 460001 _cpu_init_hook
0x80003870 1 590001 _write_r
0x800038d0 1 1090001 __call_exitprocs
...
...
./tarmac-calltree hello.trace --image hello.axf
o t:10000 l:2288 pc:0x80001148 - t:23510000 l:7819 pc:0x80008060 : frame_dummy
- t:240000 l:2338 pc:0x800011a8 - t:720000 l:2443 pc:0x800011ac
o t:250000 l:2340 pc:0x80003818 - t:710000 l:2442 pc:0x80003828 : _cpu_init_hook
- t:260000 l:2343 pc:0x8000381c - t:320000 l:2354 pc:0x80003820
o t:270000 l:2345 pc:0x80002000 - t:310000 l:2353 pc:0x80002010 : main
- t:320000 l:2354 pc:0x80003820 - t:700000 l:2436 pc:0x80003824
o t:330000 l:2356 pc:0x80003784 - t:690000 l:2435 pc:0x80003814 : main
- t:760000 l:2453 pc:0x800011bc - t:2010000 l:2970 pc:0x800011c0
o t:770000 l:2455 pc:0x80004200 - t:2000000 l:2969 pc:0x800042c0 : memset
- t:2010000 l:2970 pc:0x800011c0 - t:4870000 l:3587 pc:0x800011c4
o t:2020000 l:2972 pc:0x80007970 - t:4860000 l:3586 pc:0x80007b04 : initialise_monitor_handles
- t:2960000 l:3165 pc:0x80007b24 - t:4340000 l:3465 pc:0x80007b28
I have tried the following method to execute on QEMU, without any success.
I have started the QEMU with gdb based debugging through TCP Port
$ qemu-system-aarch64 -semihosting -m 128M -nographic -monitor none -serial stdio -machine virt,gic-version=2,secure=on,virtualization=on -cpu cortex-a53 -kernel hello.axf -S -gdb tcp::9000
The result of debug session is given below:
gdb) target remote localhost:9000
Remote debugging using localhost:9000
_start () at /data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/libgloss/aarch64/crt0.S:90
90 /data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/libgloss/aarch64/crt0.S: No such file or directory.
(gdb) si
<The system hangs here>
I have tried to disassemble the code using gdb and its output is given below. It looks like the code is not loaded correctly
(gdb) disas frame_dummy
Dump of assembler code for function frame_dummy:
0x0000000080001110 <+0>: udf #0
0x0000000080001114 <+4>: udf #0
0x0000000080001118 <+8>: udf #0
0x000000008000111c <+12>: udf #0
0x0000000080001120 <+16>: udf #0
0x0000000080001124 <+20>: udf #0
0x0000000080001128 <+24>: udf #0
0x000000008000112c <+28>: udf #0
0x0000000080001130 <+32>: udf #0
0x0000000080001134 <+36>: udf #0
0x0000000080001138 <+40>: udf #0
0x000000008000113c <+44>: udf #0
0x0000000080001140 <+48>: udf #0
0x0000000080001144 <+52>: udf #0
End of assembler dump.
Could you please shed some light on this. Any hint given is appreciated very much.
The Foundation Model and the QEMU 'virt' board are not the same machine type. They have different devices at different physical addresses, and in particular they do not have RAM at the same address. To run bare metal code on the 'virt' machine type you will need to adjust your code. This is normal for bare metal -- the whole point is that you are running directly on some piece of (emulated) hardware and need to match the details of it.
Specifically, the minimum change you need to make here is that the RAM on the 'virt' board starts at 0x4000_0000, not the 0x8000_0000 that the Foundation Model uses. There may be others as well, but that is the immediate cause of what you're seeing.

How do i run assembly (.s) files on VSCode in Linux subsystem

I have just got into ARM programming. Learned a few basics but am having issues with running code. I use VSCode on Linux Subsystem as my IDE.
I have nothing installed on my computer and i would like to run ARM code. I have read online something about "qemu" and "kernel" and stuff, but am not sure what they mean. It would be great if someone provides a detailed walkthrough for such a problem. I do not have a raspberry pi.
For example, how do i run the following division.s file on VSCode?
.global _start
_start:
MOV R1, #X
MOV R2, #Y
MOV R3, #Z
CMP R1, R2 # is x>y ?
BGT _tryx
CMP R2, R3 # is y>z ?
BGT _isy
MOV R4, R3
B _exit
_isy:
MOV R4, R2
B _exit
_tryx:
CMP R1, R3 # is x>z ?
BGT _isx
MOV R4, R3
B _exit
_isx:
MOV R4, R1
_exit:
MOV R0, R4
MOV R7, #1
SWI 0
.data
.equ X, 3
.equ Y, 5
.equ Z, 4
Are there any extensions i need to install? Is there anything i need to download? I have used gcc to compile C code. Can it be used here too?
Thx in advance! :D
Your question is rather a broad one. This being said, a slightly modified version of your program can be executed in WSL using the following procedure:
sudo apt-get install qemu-user
sudo mkdir -p /opt/arm/10
wget 'https://developer.arm.com/-/media/Files/downloads/gnu-a/10.2-2020.11/binrel/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz?revision=d0b90559-3960-4e4b-9297-7ddbc3e52783&la=en&hash=985078B758BC782BC338DB947347107FBCF8EF6B' -O gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz
sudo tar Jxf gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz -C /opt/arm/10
/tmp/division.s:
# count how often we can take Y from X
.global main
main:
MOV R1, #X
MOV R2, #Y
MOV R3, #0 # Q
_loop:
CMP R1, R2
BLT _exit
SUB R1, R2
ADD R3, #1
B _loop
_exit:
MOV R0, R3
MOV R7, #1
SWI 0
.data
.equ X, 23
.equ Y, 4
Compiling:
/opt/arm/10/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-gcc -static -o /tmp/division /tmp/division.s
Executing - WSL:
qemu-arm /tmp/division
echo $?
5
Which is the expected result, since 23 div 4 is 5.
Executing - Windows 10:
C:\>c:\Windows\System32\bash -c "qemu-arm /tmp/division; echo $?"
5
C:\>
Or:
C:\>c:\Windows\System32\bash -c "qemu-arm /tmp/division"
C:\>echo %ERRORLEVEL%
5
Note that division.s may have been compiled in Windows 10 as well by downloading/installing gcc-arm-10.2-2020.11-mingw-w64-i686-arm-none-linux-gnueabihf.tar.xz instead of gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz - your choice.
I let it to you than to go into the details of using the information above for running your program from vscode, you question being a bit too broad IMHO.
Update: division.s was compiled statically on purpose for avoiding having to specify the locations for any non-needed dynamic libraries.
Compiling it without using the -static option, and executing it would result in the following error message to be displayed:
qemu-arm division
/lib/ld-linux-armhf.so.3: No such file or directory
It can be avoided by telling qemu-arm where to look for required dynamic libraries, /lib/ld-linux-armhf.so.3 in this case:
qemu-arm -L /opt/arm/10/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/libc division
echo $?
5
That looks like a Linux program. And I guess you have an 64-bit x86 computer.
You want QEMU, specifically the executable qemu-arm which emulates an ARM processor running Linux on another Linux compatible system. In Debian derived Linux distributions it is in the package qemu-arm.
And on ebian derived Linux distributions for a compiler you can install the gcc-arm-linux-gnueabihf package for compiling for ARMv7 and ARMv8 with hardware floating point (Debian port name armhf), or gcc-arm-linux-gnueabi for some older ARMs with no hardware floating point Debian port name armel).
If you wish to install libraries, you need add the architecture to dpkg's list, for example:
dpkg --add-architecture armhf

How to write inline assembly in FreeDOS

I'm trying to write the following program to dump the interrupt vector table using FreeDOS in a virtual machine. I know that DEBUG will allow me to write an assembly program, but how do I create the following IVTDUMP.COM file, save it and run it?
Note: I'd like to try and do it all straight from FreeDOS if possible. I tried using the EDIT command but it errors out and I'm pretty sure I'm missing something.
for
(
address=IDT_255_ADDR;
address>=IDT_001_ADDR;
address=address-IDT_VECTOR_SZ,vector--
)
{
printf("%03d %08p ",vector,address);
__asm
{
PUSH ES
MOV AX,0
MOV ES,AX
MOV BX,address
MOV AX,ES:[BX]
MOV ipAddr,AX
INC BX
INC BX
MOV AX,ES:[BX]
MOV csAddr,AX
POP ES
};
printf("[CS:IP]=[%04X,%04X]\n",csAddr,ipAddr);
}
Things like for, address and printf are not part of assembly. You will have to rewrite that to actual assembly code or copy the macros and assembler you want to use to your freedos environment.
If you want to use debug as included in freedos you can use the a command to start writing assembly instructions, the n command to give a name and w to write the code to the file.
C:\debug
-a
06BC:0100 int 20
06BC:0102
-n ivtdump.com
-rcx 2
-w
Writing 0002 bytes.
-q
C:\
This sample program only exits the program through int 20. (The 2 after rcx indicates the length of the program to write to disk)

Resources