Consider using nasm instead of yasm in CMake port
Brought to you by:
sobukus
I created a few patches to improve yasm on CMake support, with the hope of finding out why CI is failing.
Since I cannot reproduce the error locally, I've not yet created a fix.
It looks like yasm is EOL.
Perhaps it makes sense to move to nasm?
See https://github.com/yasm/yasm/issues/295
So did nasm survive its fork yasm? I'm not sure about the specifics. I only used barebones as personally. Do we need to change anything in the code or is it just adapting configure and cmake scripts? Actuallyt … I do wonder if we could get rid of yasm stuff in configure.ac, as it is only for AVX from times where the default assembler didn't support it, I presume.
nasm is Intel-syntax only. So all AT&T syntax would have to be converted.
The GNU assembler supports this syntax with
.intel_syntax noprefix.It looks like nasm supports the latest intel instruction set extension (avx512/amx).
Perhaps it would be possible to assemble the sources with the Microsoft assembler and get rid of the nasm/yasm requirement for MSVC?
I spent yesterday writing a very rough converter for AT&T to Intel (see attachment).
Applying it to mpg123's assembly sources, I can build a amd64 mpg123 on Linux using the GNU assembler.
x86 is almost there, but has an issue with
LOCAL_VAR.I pushed these changes to https://github.com/madebr/mpg123/tree/assembly-intel-syntax
(I did not validate the resulting binary)
I now can build libmpg123 for x86_64 on Linux using both nasm and gas.
Let me know what you think of the current approach.
I'm verifying the equivalence between intel syntax (gas and nasm) against the original AT&T sources by comparing the output of
objdump -d <obj>of the objects, and so far everything seems to be looking good.That needs some thought … for clarification: Do you intend to only use the translated files for nasm/Windows or rather aim for replacing all old .S files with new intel-style ones?
Reading https://wiki.osdev.org/GAS#Intel_Syntax_Support … I guess forking translations only to be used with nasm seems safer, also not touching the other assembly sources
Last edit: Thomas Orgis 2026-07-21
The other approach for x86-64 and ARM would be trying if re-implementing the ASM with intrinsics does work well. Would they offer the same performance? I see weird subtle effects when re-arranging C code, a few percent performance are lost easily with innocently-looking changes.
The intention is to replace all AT&T sources with Intel version. They are currently added with a
-intelsuffix (for easy comparison), but the originals should be 100% replaced by their Intel counterparts.The wiki says Intel syntax is supported since binutils 2.10 (2000-11-07), so well old enough?
With C intrinsics, you depend on the compiler allocating the registers in a way that the hot loop does not spill them to the stack, so similar performance is not assured.
Looking at this table, by using Intel syntax, all assemblers are unlocked (in principle).
Last edit: Maarten 2026-07-21
I am referring to this paragraph from osdev wiki:
It is generally discouraged to use
the support for Intel Syntax because it can subtly and surprisingly different than the real Intel Syntax found in other assemblers. A different assembler should be considered if Intel Syntax is desired.
Has that changed? Do we need a checker that we keep gas' dialect of Intel syntax?
Regarding intrinsics: I'd suspect that they will be somewhat distant from optimal. Though the hope still remains that compilers at some point can create fast numerical code ... with some hints about allowed tradeoffs...
I also wonder how many CPU and object format features will keep cropping up to annoy me, having to update the asm files with random new sections, flags, and instructions (bti, nonexec stack).
That points towards having only one version per asm file. And if the okd x86 ones are translated, comparison of generated objects should be the standard, as you started out with, otherwise we'd need to dig out the actual CPUs concerned to make proper comparisons.
--
sent from mobile device, trustworthy or not
In the past, Intel syntax support of the GNU assembler might have been spotty but right now it feels very good. I have more "problems" getting the code accepted by nasm and masm.
In the mean time, I have MASM x64 working: see https://github.com/madebr/mpg123/actions/runs/29977815128/job/89113219065
So the assembly code can now be assembled by NASM, GASM and MASM
I feel the amount of additional complexity is relatively low. The differences lie in:
rip)0xabcdef, MASM needs0abcdefh)dword ptrand similar, NASM does not recognize theptrkeyword, GASM does not care whether it is present)ddfor nasm and msasm,.longfor gasm)align XXonly works in msasm if and only if the containing segment has an alignment that is a multiple ofXXI was able to support all of them without a single
#if/#else/#endifin the.textsegment. All is handled by macros defined in the prolog.Last edit: Maarten 2026-07-23
Nice. So when MSASM works ... we actually don't have a case for needing NASM anymre, right? I'd like to drop the configure stuff for that ...
Clang should be happy where gcc/gas is, or not?
sent from mobile device, trustworthy or not
If yasm is only for MSVC support, then NASM can be removed.
I did in the pr I just created. My pr removes yasm from the CMake files, but leaves autotools alone.
I added a script (to a branch) that compares the disassembly between current mpg123 master and the changes.
I think they are within the expected range :
ALIGN 16in a text segment behaves different: yasm only addsNOPs,. MASM adds more complicated instructions such asNOP,LEA ESP, [ESP], ...I started getting the ARM64 assembly building using a MSVC toolchain, but I am stuck on what the correct syntax is for loading an address.
link to ci output
I tested building mpg123 with LLVM 22.1.8 on Windows, and it linked without errors.
I saw this warning:
That crt/posix crap again? I guess we can do definery to
_readand friends on Windows. Or … I'm not sure. Didn't we do this already? I remember this issue, but right now am too occupied carrying the fire hose around for the recent memroy corruption reports.Look at
and
in compat.c.
So we just need more of those for read and write? I added wrapped use of
_writeand_readin compat.c with svn rev 5627.Can you confirm that this works now? Are there other places with that warning?
Ping. I guess it's time to revisit that, now that I finally got around extending the id3v2 code that I had in front of me for so long.
Simplifying configure/build is a motivation for me, even if I don't really like touching all assembly files that much.
Did the change on the posix I/O functions work to get rid of warnings on Windows?
It's a 1:1 mechanical translation using the script shared in this post (additional changes were applied for MASM support, and then removing NASM). I only hooked up my changes in the CMake build scripts.
I added a compare script in the
add-compare-scriptbranch.Run
python compare-objects.py build-unixto build mpg123 4 times (2x for x86/x86_64 each, and 2x for before and after the changes).Run
python compare-objects.py compare-unixto compare the objects.I just tried building mpg123 on Windows, and ran in the following error using LLVM (with MSVC headers):
This patch fixed the error:
Ah, these make more sense inside compat.h, no?
Like that? Could add a branch for the default 0, 1, 2 values, too, for other platforms.
I did a test with MSVC, msys2 mingw64 and llvm:
_WIN32, but only mingw64 definesWIN32.CMake adds
/DWIN32by default, but the define can trivially be removed._WINDOWSmacros, which none provide out-of-the-box.CMake also adds a_WINDOWSmacros, which none provide out-of-the-box.So I suggest to only use
_WIN32.Using
_WIN32, that works.Maybe have a fallback?
Last edit: Maarten 6 days ago
OK, thanks. I'll try to remember
_WIN32as the thing to use.I'll need some time to verify the asm stuff, including the mangle.h changes. Since it's been decades of glueing stuff on top of initial creations of the elders, I'm very conservative and want to be sure we don't miss any corner case. At the same time, I have little time available for the task … but we'll get there, eventually.
How far are you with ARM64 on MSVC?
Also, to get a bit outside the box: The motivation of changing sources at all is builds on Windows using MSVC toolchain with its assembler. The relevant platforms for that are AMD64 and ARM64, right? Modern stuff. So the minimal set to have 'new' assembly for AVX and NEON64, isn't it? Is actual 32 bit Windows a thing, still? Embedded systems to put an mp3 player into? If not, we're talking about two targets .. ? This also means, though, that I exclude MSVC builds from providing the run-time CPU choice of the x86 binary. We'd have only generic and AVX. But maybe that's appropriate.
I am a bit wary of the variations in syntax that you do manage to support. Iit is mental effort also for anyone trying to work on the codebase. Granted, there have been variations before, too, but it doesn't get simpler.
Even if you verify the produced objects, I wonder if we could/should get away without touching the code for 3DNow! at all, for example. It is mostly of historic relevance, but it will stay around for people needing the fastest mp3 decoder on their little project with a historic CPU and some old i686 Linux base. Maybe I figure that it's all trivial/safe enough after all, but I need time assessing. If we'd just add intel-translated files for the few use cases for MSVC (and a separate/add-on mangle.h, perhaps) and limit the build system to use them only when GAS is not in use, it would be easier for me to get the foot off the brake.
Of course you can suggest an all-in translation of all sources is simpler than having a special case for assemblers with intel syntax; or one special case for Windows+MASM, for that matter.
PS: Thinking a bit about why I am hesitating so much … maybe it is just that the secondary platform is prompting unwanted change in the most sensitive parts of mpg123 where Unix builds are fine with the state as-is. I am still pondering writing an intrinsics implementation that would benefit anyone with a modern toolchain. Then the stand-alone .S files would be optional for people wanting to support old x86 or ARM CPUs.