using-libasm
Skill4 starsChanged 7 months agoMITView on GitHub
Library of routines for RISC OS C programming. Provides optimized multiplication/division, processor identification, IRQ control, floating-point preservation, and non-C (registrant) function calls. Use when C code needs assembly-level functionality or when porting code that requires these low-level operations. The library is linked by adding C:Asm.o.libAsm to the LIBS line in a makefile and included via headers like #include "Asm/muldiv.h".
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 127
When using floating-point operations in SVC mode (e.g., from a Wimp filter), the FPU registers must be preserved because the APCS declares …
- Very specific: line 170
Why use
_callx?: When you need to call a function (e.g., a registered handler ), _callx provides a clean interface for passing arguments …
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Using libasm
Overview
libasm is a C-callable library containing optimized assembly routines that are useful when writing RISC OS applications and modules in C. The library provides several categories of functionality:
- Multiplication and division - 64-bit intermediate arithmetic to avoid overflow
- Processor identification - Runtime detection of ARM architecture and processor type
- IRQ control - Safe masking and unmasking of interrupts
- Floating-point preservation - Saving/restoring FPU state when using FP in SVC mode
- Non-C function calls - Calling arbitrary functions with register arguments
- Task management - Safely calling
Wimp_StartTaskfrom SVC mode
The library is distributed as an object library that you link into your project. It should not be used directly from BASIC - these are C helper routines.
Installation and Usage
Linking in a Makefile
To use libAsm, add it to the LIBS variable in your Makefile,fe1:
LIBS = ${CLIB} C:Asm.o.libAsmNote: Asm.o.libAsm (32-bit) are available. The 64-bit variant is not available.
Including Headers in C Code
Include the relevant headers in your C source files using the Asm/ prefix:
#include "Asm/muldiv.h" /* Multiplication and division */
#include "Asm/processor.h" /* Processor identification */
#include "Asm/irqs.h" /* IRQ control */
#include "Asm/fpsvc.h" /* Floating-point preservation */
#include "Asm/callx.h" /* Cross-mode function calls */
#include "Asm/callbacks.h" /* Triggering callbacks */
#include "Asm/starttasksvc.h"/* Wimp_StartTask from SVC mode */Available Routines
Multiplication and Division (Asm/muldiv.h)
The muldiv() function performs (a * b) / c with a 64-bit intermediate product,
avoiding overflow that would occur with standard 32-bit multiplication.
#include "Asm/muldiv.h"
int result = muldiv(100, 200, 50); /* Returns (100 * 200) / 50 = 400 */Why use muldiv? Standard C multiplication of two 32-bit values can overflow before
division. The muldiv function performs the calculation internally using 64-bit arithmetic
to preserve precision.
Processor Identification (Asm/processor.h)
processor_id() returns the ARM processor ID register value, which encodes the processor
type, architecture, and revision.
#include "Asm/processor.h"
unsigned long id = processor_id();The header provides macros to interpret the processor ID:
| Macro | Description |
processor_architecture(id) | Returns an procarch_t enum value for the architecture |
processor_is_arm6x0(id) | Non-zero if running on an ARM6x0 series processor |
processor_is_arm7(id) | Non-zero if running on an ARM7 series processor |
Architecture enum values:
| Enum | Architecture |
arch_2 | ARM2/ARM3 |
arch_3 | ARM6/ARM60 |
arch_4 | ARM7500-style (Architecture 4) |
arch_4T | ARM7TDMI (Architecture 4T) |
arch_5 | StrongARM (Architecture 5) |
arch_5T | Architecture 5T |
arch_5TE | Architecture 5TE |
arch_5TEJ | Architecture 5TEJ |
arch_6 | Architecture 6 |
IRQ Control (Asm/irqs.h)
These functions safely manipulate the interrupt mask bits in the processor mode register.
#include "Asm/irqs.h"
unsigned long flags;
flags = ensure_irqs_off(); /* Disable IRQs, save previous state */
/* Critical section */
restore_irqs(flags); /* Restore previous state */
flags = ensure_irqs_on(); /* Enable IRQs, save previous state */
/* Section where IRQs must be on */
restore_irqs(flags); /* Restore previous state */Why use these? Direct manipulation of the SPSR or CPSR is error-prone. These functions provide a structured way to disable/enable interrupts while preserving the previous state, which is essential for interrupt handlers and critical section code.
Floating-Point Preservation (Asm/fpsvc.h)
When using floating-point operations in SVC mode (e.g., from a Wimp filter), the FPU registers must be preserved because the APCS declares F0-F3 as corruptible.
#include "Asm/fpsvc.h"
void my_svc_function(void) {
int result;
fpsvc_buf fpbuf;
fpsvc_preserve(&fpbuf);
/* Do floating-point operations here */
result = calculate_value(3.14159);
fpsvc_restore(&fpbuf);
}Why use this? Without preserving FPU state, your code may corrupt the floating-point context of the task that called your SVC-mode code, leading to incorrect calculations or crashes in the calling application.
Non-C Function Calls (Asm/callx.h)
_callx() allows you to call an arbitrary function with register arguments, similar to
_swix() but for function calls rather than SWIs.
#include "Asm/callx.h"
#include "swis.h"
/* Call a function with R0-R4 as arguments, R0 as output */
void *func_ptr = some_function;
void *func_pw = module_pw;
int result;
/* Mask format: bits 0-11 = input registers: `_IN(reg)` and `_INR(loreg,hireg)`
bits 22-31 = output registers: `_OUT(reg)` and `_OUTR(loreg,hireg)` */
int result;
_callx(func_ptr, func_pw, _INR(0,4)|_OUT(0), arg0, arg1, arg2, arg3, arg4,
&result);Why use _callx? When you need to call a function (e.g., a registered handler
), _callx provides a clean interface for passing arguments and receiving
results, similar to how _swix works for SWIs.
Callback Triggering (Asm/callbacks.h)
trigger_callbacks() drops to user mode to allow pending callbacks to be processed.
#include "Asm/callbacks.h"
/* During a long-running operation */
for (int i = 0; i < 1000; i++) {
do_work_step(i);
if ((i % 100) == 0) {
trigger_callbacks(); /* Allow Wimp tasks and callbacks */
}
}Why use this? Long-running code in SVC mode can prevent the Wimp from processing callbacks (e.g., TaskWindow events, mouse movements). Dropping to user mode briefly allows the system to update and respond to user input.
Wimp_StartTask from SVC (Asm/starttasksvc.h)
svc_wimp_start_task() safely calls Wimp_StartTask from SVC mode by dropping to USR
mode first.
#include "Asm/starttasksvc.h"
unsigned long taskhandle = svc_wimp_start_task("SWidget swidget", 0);
if (taskhandle != 0) {
/* Task started successfully */
}Why use this? Wimp_StartTask cannot be called directly from SVC mode because it
triggers a task switch. This function handles the mode switch correctly and returns the
task handle without corrupting the USR mode stack.
Common Patterns
Safe Critical Section with IRQ Control
#include "Asm/irqs.h"
void update_shared_data(void) {
unsigned long flags = ensure_irqs_off();
/* Atomic update of shared data structure */
shared_counter++;
shared_flag = TRUE;
restore_irqs(flags);
}Architecture-Specific Code
#include "Asm/processor.h"
void init_hardware(void) {
unsigned long id = processor_id();
switch (processor_architecture(id)) {
case arch_4:
case arch_4T:
init_arm7_hardware();
break;
case arch_5:
case arch_5T:
case arch_5TE:
init_strongarm_hardware();
break;
default:
init_generic_hardware();
break;
}
}Floating-Point in a SWI call
#include "kernel.h"
#include "Asm/fpsvc.h"
_kernel_oserror *my_filter(_kernel_swi_regs *r, void *wb) {
fpsvc_buf fpbuf;
fpsvc_preserve(&fpbuf);
/* Use floating-point calculations */
float scale = 1.5f;
float value = compute_value() * scale;
fpsvc_restore(&fpbuf);
return NULL;
}Long-Running Operation with Callbacks
#include "Asm/callbacks.h"
void process_large_file(void) {
for (int block = 0; block < total_blocks; block++) {
process_block(block);
/* Allow callbacks every 100 blocks */
if ((block % 100) == 0) {
trigger_callbacks();
}
}
}Build Notes
- The library is only available for 32-bit builds. There is no 64-bit variant.
- The
_callximplementation is already present in the 64-bit C library.
- The
- The standard variant (
libAsm) is for application use. - The module variant (
libAsmzm) is position-independent and safe for ROM inclusion.
See Also
writing-cmodules- For integrating this library into RISC OS modules.using-makefiles- For linking libraries in RISC OS makefiles.
In this repository47 other files it gives its agents.
- allocating-resourcesSkill
- ci-testingSkill
- creating-pull-requestsSkill
- designing-modulesSkill
- porting-to-riscos-cSkill
- reading-assemblySkill
- riscos-commandsSkill
- riscos-desktop-fileractionSkill
- riscos-filer-likeSkill
- riscos-filesystemSkill
- riscos-graphics-convertersSkill
- riscos-network-dcistatisticsSkill
- riscos-network-resolverSkill
- riscos-outputSkill
- riscos-reSkill
- riscos-styleSkill
- riscos-throwbackSkill
- riscos-urls-fetchingSkill
- riscos-urls-launchingSkill
- riscos-wimp-appSkill
- riscos-wimpSkill
- riscos-wimp-templatesSkill
- updating-robe-skillsSkill
- using-bbcbasicSkill
- using-cmhgSkill
- using-ghSkill
- using-gitSkill
- using-libgcontextSkill
- using-liboslibSkill
- using-libriscoslibSkill
- using-libtoolboxSkill
- using-makefilesSkill
- using-perlSkill
- using-stronghelpSkill
- using-toolbox-imagefilegadgetSkill
- using-tooltesterSkill
- writing-assemblySkill
- writing-assembly-testsSkill
- writing-cmodulesSkill
- writing-cplusplusSkill
- writing-cSkill
- writing-fortranSkill
- writing-oslib-defsSkill
- writing-pascalSkill
- writing-prminxmlSkill
- writing-pymodulesSkill
- writing-pyromaniac-integration-testsSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

