16 ms·
New inline assembly syntax available in Rust nightly
- open-paren 6y agoI'm new to Rust, so there may be precedent that I don't know, and I'm kinda spoiled because I'm a front-end dev mainly, where the rule is "don't break the web", but doesn't changing the syntax of a macro like that break backwards compatibility?
- whatshisface 6y ago`asm!` never made it out of the nightly builds, so nothing that's being changed has been released.
- dralley 6y agoThe important thing in this case is that the previous syntax was never actually stabilized, and was only available in nightly releases of the compiler. So technically it does break some code, but only code which was deliberately opting into unstable features with the knowledge that it may break in the future.
- jcranmer 6y agoasm! has been an unstable feature for years, which means a) it's available only in nightly builds, and b) there is no guarantee that it will remain backwards-compatible. Actually, with regards to asm!, it's been known for a long time that it was unlikely to be stabilized as-is (being originally a very thin wrapper around LLVM's inline asm functionality). Probably nearly everyone who's been relying on inline asm to make their code work has already been following the effort to replace asm! with a better version.
- gpm 6y agoc) Even on nightly builds you need to put #![feature(asm)] at the root of your crate to use it. (Likewise for all unstable features, just replace asm with feature_name.)
- twic 6y ago> Probably nearly everyone who's been relying on inline asm to make their code work has already been following the effort to replace asm! with a better version Except for my colleague who basically says "nah, they'll never be able to move off the LLVM syntax, the code i'm writing now will be supported forever". Fortunately, we only have a small amount of assembly, so if we ever do want to upgrade to a version of the compiler which has dropped support, it won't be a lot of work.
- dathinab 6y agoSupport will likely not be dropped anytime soon, maybe never. You just need to rename it to `llvm_asm!`. Through with `asm!` likely going to be stabilized while `llvm_asm` never going to be stabilized it might be worthwhile to switch to the new asm to get of nightly in the future ;=)
- trufas 6y agoEvery couple years they'll define an edition of a language (e.g. rust 2015, rust 2018), the idea being that if you choose to stick to one of them, the latest rust will still compile your code as long as you tell it what version you're targetting.
- JoshTriplett 6y agoThis isn't related to editions; asm was never stable syntax and couldn't be used in the stable compiler; you could only use it on nightly and only if you opted in. This new syntax is something we hope to stabilize eventually.
- knome 6y ago> syntax was highly unlikely to ever graduate from nightly to stable Rust, despite being one of the most requested features. I think it's safe to infer from this line that there was not yet a guarantee of stability in the interface, and that breaking backwards compatibility was therefore fine. >We renamed the existing asm! to llvm_asm! They also kept the existing functionality under a different name to ease transition. Current users will need only update the macro name and then transition to the better syntax at their own pace.
- amalcon 6y agoTo clarify, "unstable" in rust-speak means "You can use this, but it might completely change or go away, and therefore break your code." You need to deliberately opt in to unstable features, so you are unlikely to use something like this by accident.
- brandur 6y agoAlso worth noting that the old syntax was renamed from `asm!` to `llvm_asm!`. It'll still disappear at some point, but existing users of the former on nightly have a very easy way of fixing their build in the meantime.
- SpaceNugget 6y ago"don't break the web" type issues are not really applicable to releases of precompiled languages or applications that ship their own interpreters and don't load third party content. Let's say you are browsing my website. Suddenly, your browser gets an update and prompts you to re-open the window. My site no longer displays correctly due to a backward incompatible change. My site is the web and your browser broke it. If you use a native app or service I write in rust 1.35 or whatever and there is a backwards incompatible change in a new version of rust it has no impact on your use of that app at all.
- dtech 6y agobackwards compatibility is still highly valued. Code no longer compiling in newer versions of the languages can create huge churn. It's one of the reasons Java is so widely used, you can still use Java 1.4 libraries in Java 13 and most 1.4 code will keep working and compiling.
- coding_lobster 6y ago>I'm a front-end dev mainly, where the rule is "don't break the web" left-pad flashbacks intensify
- SAI_Peregrinus 6y agoRust has two ways of ensuring forwards compatibility (or incompatibility): The first is the `stable`/`nightly` system. Anything in `stable` gets compatibility guarantees, anything in `nightly` can change or be removed at any time. Nightly also has feature-gates: using an unstable feature requires an opt-in to enable it. The old `asm!` syntax which got renamed was only ever in `nightly`. The compatibility guarantees for `stable` are based on editions: each year there's an edition, your project's `cargo.toml` specifies which edition your code is for, and compilers will continue to support old edition code. New editions might require changes to existing code, but as long as you don't update the edition in your `cargo.toml` you can freely update your compiler (to a new stable version) without worrying about it breaking. You can use crates (packages) from any edition with any other edition, as long as the compiler is new enough to support the latest edition used.
- whatshisface 6y agoHopefully this will help us get better numerical libraries for scientific computing.
- Q6T46nT668w6i3m 6y agoI hope so too but I’m skeptical. In my opinion, Rust still needs ergonomic multi-dimensional index expressions and standardized multi-dimension array traits. I’d love to see (or join) a scientific working group to help with this.
- whatshisface 6y agoThat would be amazing, but I would also be satisfied with a numpy clone. Of course language-level support would be far better!
- Q6T46nT668w6i3m 6y agoI can envision something between the two, e.g. a situation similar to the Future trait and the various async backends.
- adrianN 6y agoThe lack of such features did not prevent numerical libraries in C.
- Q6T46nT668w6i3m 6y agoOr Rust (I don’t understand your point)
- adrianN 6y agoAs the topic was inline assembly, I interpreted "better" as "faster", not "more ergonomic".
- devit 6y ago
- jfkebwjsbx 6y agoAnybody that knows about the RFC and other implementations in C compilers, why are always "string literal parameters" (quoted strings) used? Wouldn't be nice to have a way to embed other languages without the need for those quotes everywhere? I guess it is meant to avoid complicating the syntax/grammar reusing the existing macro one?
- Sharlin 6y agoFor maximum generality and compatibility, likely. Also note that this is ”just” a macro, not first-class language syntax, so any non-quoted arguments would have to be valid Rust token trees.
- est31 6y ago> any non-quoted arguments would have to be valid Rust token trees. Token trees allow a very wide set of syntaxes. rust-c for example allows you to embed inline C code as token tree via a macro: https://github.com/lemonrock/rust-c https://github.com/lemonrock/rust-c
- deleted 6y ago[deleted]
- kevincox 6y agoYes, Rust macros have certain syntax requirements that allow the code to parse without knowing what a macro does (and to find out where a macro ends). Don't quote me but there are some token requirements as well as balanced parenthesis. If you allow another language to be inserted raw you risk that it requires syntax that would break these requirements. Buy using a raw string literal you have a well defined quoting syntax mediating the two languages.
- deleted 6y ago[deleted]
- klyrs 6y agoZig has a nice solution for that: https://ziglang.org/documentation/master/#Global-Assembly https://ziglang.org/documentation/master/#Global-Assembly The "magic" being that lines beginning with double-backslashes are string literals.
- amluto 6y agoRust folks, thank you so much for making this far, far better than GCC’s asm syntax for C. Also, thank you for using Intel x86 syntax instead of AT&T. It would be delightful if GCC were to adopt something similar after this stabilizes in Rust.
- pjmlp 6y agoStill fails short of asm code blocks of PC based languages.
- systems 6y agowhat are PC based languages ? what is PC short for in this context
- pjmlp 6y agoMS-DOS/Windows heritage. Modula-2, Pascal, C, C++, Basic based compilers with inline Assembly parsers or intrisics that interact with host language type system instead of manually dealing with strings UNIX style.
- dathinab 6y agoBut in rust asm! does interact with the type system. The asm macro does know about what group of registers (or what specific register) a input/output is stored/loaded from and compilation will fail if the input isn't compatible with the register. Then it's delegating to a assembler for the rest. Sure it could also have a list of all asm commands the given target does support and parameters/registers it can be used with but this means keeping track of all supported targets and all commands for all potential featuresets of all targets and all way they can be called. This is a lot of work. Even more such support can be added later one, too. For now it's more important to support asm on stable. Also with proc-macros you can implement this as a library on top of `asm`! Also with a more "knowledgeable" asm any support for a new platform would need to manually add support for all asm of that language so having a standard stringly interface is a good think anyway.
- livre 6y agoI may be the only one but I feel like this (and the old) asm syntax is too complex and not very user friendly. It looks heavily inspired GCC. I'm sorry for the upcoming German (you can ignore it and just read the examples), I feel like a smarter compiler could have a friendlier asm syntax, similar to the one used by FreeBASIC[1]. I hope you can see why I prefer that. Even though the FB compiler is not very smart and just pushes and pops all important regs to and from the stack its asm syntax is a joy to write. I don't have to specify clobber registers, in, out and variables and functions are in scope by default. Also the asm code is not a string and doesn't need to be quoted, it's doesn't look like something foreign at all. I know that something like that is currently not possible in Rust but I'd love to see it some day. [1] https://www.freebasic-portal.de/befehlsreferenz/inline-assembler-434.html https://www.freebasic-portal.de/befehlsreferenz/inline-assem...
- zozbot234 6y ago> I feel like a smarter compiler could have a friendlier asm syntax, similar to the one used by FreeBASIC[1]. Feel free to propose a better syntax, then. This feature is not yet part of Stable Rust, so syntax improvements are very much possible. The FreeBASIC syntax seems problematic though, since it would require architecture-specific smarts in the compiler and make it hard to port it to different architectures or add support for newer asm features. It might be better to have these additional features as separate tooling or crates, that might even wrap the asm! syntax itself via proc macros.
- livre 6y agoSadly I think Rust's way is the best one in the long term even if it's not very user friendly. There are a lot of problems with the FreeBASIC syntax, my comment was mostly wishful thinking. As other user has said in a reply to my comment, you can't beat the level of control Rust's syntax provides and that's what most people writing assembly would want. You are also right that a proper asm parser would be difficult to maintain due to the amount of architectures Rust has to support.
- fluffything 6y ago
- pjmlp 6y agoSadly it is yet another language that follows the UNIX tradition of not having a proper Assembly parser instead forcing us to play with strings. I guess it leaves PC based languages to have actual inline Assembly parsers or intrisics.
- jerf 6y agoI'm sure someone will be along to provide a wrapper macro or macros to address that shortly. I can see why they would not want to bless a particular syntax tree or whatever into the core compiler.
- gpm 6y ago(Once this is stable) haven't they blessed a particular syntax tree anyways, since the contents of the "" string is parsed to a specific syntax tree that will have to remain stable. The only difference is that that syntax tree is delimited "<contents>" instead of asm!(<contents>).
- Someone1234 6y agoIf you want the outer language to be cross platform (e.g. x64, ARM64, etc), then you'd either need a parser for every potential platform (even ones you aren't currently using!) OR you just settle for strings. Don't get me wrong: Parsed assembly is superior because you can have certain parser guarantees/checks. But it will definitely limit the scope of your language or at least slow its adoption to new platforms.
- mkchoi212 6y agoThis looks a lot better than GCC’s asm. However, I can’t think of a good reason why one should use asm in their code instead of letting the compiler write the far superior asm for you.
- xyproto 6y agoYou can't explore undocumented CPU instructions, like this guy is doing: https://youtu.be/jmTwlEh8L7g https://youtu.be/jmTwlEh8L7g
- yoshuaw 6y agoOne example is authoring USDT probes. This is done by writing inline assembly comments [1] that the kernel can then trace when instructed to. Also people doing cryptography things occasionally need access to specific ASM instructions for their work. I believe AES has specialized instructions, but there are more cases. You're not wrong that writing inline ASM is a fairly specialized need, but for those who require it this will come in incredibly useful. [1]: I still need to try using this, so I might be wrong. I was waiting on inline assembly to be available before trying tho, so quite excited it's now available.
- mkchoi212 6y agoYeah true. But doesn’t Rust provide an equivalent to C’s intrinsic functions like popcount?
- MaulingMonkey 6y agoYes: https://doc.rust-lang.org/core/intrinsics/fn.ctpop.html https://doc.rust-lang.org/core/intrinsics/fn.ctpop.html https://doc.rust-lang.org/std/?search=count_ones https://doc.rust-lang.org/std/?search=count_ones There are still use cases for raw assembly untouched by the optimizer - e.g. constant time cryptography functions designed to thwart timing attacks might desire control over the exact instruction stream. Although, most of that can be tackled with out-of-line assembly - as one must do with x64 MSVC for example.
- 6y ago
- dathinab 6y agoI recommend reading the RFC. It explains pretty well how it works and it's readable even for people with only very minimal asm experience: https://github.com/Amanieu/rfcs/blob/inline-asm/text/0000-inline-asm.md https://github.com/Amanieu/rfcs/blob/inline-asm/text/0000-in...
- Bedon292 6y agoI am super new to Rust and maybe not the best place to ask, but why would you want to use inline assembly in Rust at all? Does that not invalidate a lot of the safety features built into the language?
- deleted 6y ago[deleted]
- metalliqaz 6y agoIf you have a large-ish project that is otherwise coded in Rust, but you have to do some low-level coding because of special I/O, or special intrinsic features for multimedia, or even just flat-out performance, then this allows you to do so without falling back on linking against ASM or C.
- learc83 6y agoRust wants to be a serious contender for low level and embedded code. In those spaces sometimes you don't have much of a choice but to drop down into assembly.
- woodruffw 6y agoRust has lots of unsafe features; they all require explicit `unsafe {}` blocks. As the post mentions, inline assembly comes in handy in a number of low level contexts (e.g. dealing with memory-mapped devices, working on microcontrollers, using processor features that aren't exposed by the kernel or standard library).
- gizmo385 6y ago> using processor features that aren't exposed by the kernel or standard library). As someone who doesn't do any low-level work, could you give an example of these kinds of features? I'd like to read into some of them :)
- fluffything 6y agoJust take any operating systems course and try to implement your own. Or try to program a micro-controler "hello world" that actuates an LED ?
- artursapek 6y agoIf I wanted to learn assembly language in 2020, what's the best book or resource people would recommend?
- thomspoon 6y agoImo there’s not really a best book or resource other than buying a microcontroller and doing it yourself! Pick up a ARM Cortex-M4 development board either from TI or STM and reimplement their example code or driver code in assembly! You can look at the ISA to see what assembly instructions are supported, or the disassembly of a running program (probably with no optimizations so you can see what they are doing)
- jagger27 6y agoThere’s definitely something to be said about poking a physical pin in assembly. It makes me feel like I actually have control of the computer, and that I’m not just along for the ride.
- adamnemecek 6y agoI really like "Introduction to 64 Bit Assembly Programming for Linux and OS X: For Linux and OS X" by Ray Seyfarth. It's short and you actually implement something interesting like the correlation function or basic data structures, like linked list.
- artursapek 6y agoThanks!
- ethagnawl 6y agohttps://famicom.party https://famicom.party features the best, most accessible 6502 assembly crash course I've yet to come across. It does strike me as weird that there aren't any popular resources that sit between something as high-level as the linked e-book and something as low-level as "buy some hardware and figure it out".
- Teknoman117 6y agoTo be honest, I still like the explicit cobber syntax of rusty_asm. Last year I had some fun getting a rust program to run on some old 386 DOS SBC I had hanging around. Was terrible in terms of code density (basically a bunch of 32 bit instructions prefixed with the "execute 32 bit op in real mode" prefix). This was a wrapper around the DOS string print function (where s is a &str). rusty_asm! { let ptr: in("{dx}") = s.as_ptr(); let len: in("{cx}") = s.len(); clobber("ah"); clobber("al"); clobber("bx"); asm("volatile", "intel") { "mov ah, 0x40 xor bx, bx int 21h" } }
- JoshTriplett 6y agoIn the new syntax, a direct translation of that would look something like this: asm!(" mov ah, 0x40 xor bx, bx int 21h ", in("dx") s.as_ptr(), in("cx") s.len(), out("ax") _, out("bx") _, ) However, I'd personally write that like this instead: asm!( "int 21h", inout("ax") 0x4000 => _, inout("bx") 0 => _, inout("cx") s.len() => _, inout("dx") s.as_ptr() => _, ) That lets the compiler handle filling in ax and bx, and also avoids trusting that the interrupt routine leaves ax/bx/cx/dx untouched. (I might also write clobbers for every other general-purpose register, too. Take a look at Linux arch/x86/boot/bioscall.S and the "Glove box" for BIOS calls, due to misbehaving BIOSes that clobber registers they shouldn't.)
- Teknoman117 6y agoThanks! The latter of the two is definitely nice. Yeah, I should've let the compiler setup ax and bx. Again, this was a hack :)
- josephcsible 6y agoI agree that passing `ax` and `bx` as inputs is better than setting them in the inline asm, but I don't like the idea of setting registers that shouldn't get changed as outputs "just in case".
- mhh__ 6y agoI don't understand (I do actually but it's not that much work) why so few languages do what D does and actually have inline assembly as a fully supported (no quotes) syntactic construct within the language
- cowboysauce 6y ago> I do actually but it's not that much work It apparently is, given that D only supports x86 assembly, doesn't support all instructions and has idiosyncrasies like requiring prefixes to be written as separate instructions.
- MintelIE 6y agoIs Rust ever going to go for standardization? Seems like the language has been in a state of flux with heavy changes all the time. When's it going to settle down a bit?
- sedatk 6y agoAs long as it's backwards compatible, why should that be a problem?
- pjmlp 6y agoUse of Rust on domains that require compilers for ISO and ECMA certified languages.
- simias 6y agoKeep in mind that the changes since 1.0 have been with very few exceptions completely backward compatible. I write a significant amount of Rust and I don't follow the development of the language ultra closely anymore, yet it doesn't feel like I'm coding for a moving target. Basically from my point of view the changes are about adding features (inline ASM in this case, async I/O previously) but it doesn't really change the way you code, it's just an other tool in your belt that you may decide to use later. If you didn't have a need for inline ASM before you still won't be using it, if you couldn't use Rust previously because of bad ASM support it opens up new use cases.
- deleted 6y ago[deleted]
- gonational 6y agoI don’t know much about the topic, but I am curious: does this open Rust up to being less “safe” (in the Rust sense of safety)? C is of course higher level than assembly and I understand that C is very much not “safe”, so it makes me wonder whether this gives library developers incentives to add code that has a higher likelihood of creating security bugs while optimizing their code. Is there any reason to believe this could be the case, or am I just misunderstanding how all of this fits together?
- _bxg1 6y agounsafe { } blocks already exist, and in fact it looks like these have to go inside of them. Rust can do unsafe things, it just goes to great lengths to empower you to avoid accidentally doing unsafe things. It also forces you to label all unsafe code with an easily-searchable demarcation.
- andolanra 6y agoThis does not make Rust less safe. The capability to use assembly is already there: either by using the existing assembly syntax, by linking to C code, or by linking to assembly routines directly. In order to use this, you need to use the unsafe keyword in order to indicate to Rust, "I am aware that the guarantees that Rust provides to me are not applicable when using this feature." This is true of all the existing ways of interfacing with non-Rust or assembly code, and it does not change with this new syntax.
- m0zg 6y agoIs there anything like https://github.com/herumi/xbyak https://github.com/herumi/xbyak on the Rust side? I like this approach a lot for non-tivial high performance work since it lets you tweak your assembly for particular hardware at runtime.
- JoeAltmaier 6y agoAlways tricky. I avoid inline assembler, except in cases where the compiler cannot generate some special instruction. This can occur in drivers and kernel code, where there's no other language feature to manipulate processor architecture (special registers or machine state manipulation). It can be fun to try and hand-optimize code in regular applications. I can't help but feel, there's more juice in teaching the compiler to recognize the case and generate better code instead. But few know how to go down that road.
- saagarjha 6y agoTeaching compilers works in most cases, but not all of them. Sometimes the language just does not have ways of expressing things to the compiler that you would like it to know. (For example, how would you explain to the compiler that reading within the same page will not trigger a fault? Such a guarantee is often used in vectorized strlen functions, for example.)
- WalterBright 6y agoThe inline assembler syntax used in D is designed to match the syntax used in the Intel assembler reference manuals. It's not that the Intel syntax is that great (it isn't) but the mental gymnastic of having to swap the operands makes blood run out of my ears, and causes me to make huge numbers of mistakes.
- xiaodai 6y agoBro. First, unsafe and now assembly. How is Rust a safe language?
- nitsky 6y agoThere are two languages, “rust” and “unsafe rust”. All code in unsafe blocks is not safe.
- cesarb 6y ago> All code in unsafe blocks is not safe. That's a sadly common misconception. The unsafe blocks only enable a few extra language features, like dereferencing raw pointers and calling unsafe functions; if none of these extra language features are used, the code is completely safe. That is, if you have a block of code ({ X }) and just add the unsafe keyword (unsafe { X }), it works exactly the same and is still safe. This also shows that there are not "two languages"; what you called "rust" is a subset of what you called "unsafe rust", not a different language.
- nitsky 6y agoThe first paragraph of the chapter on unsafe rust in TRPL reads: > However, Rust has a second language hidden inside it that doesn’t enforce these memory safety guarantees: it’s called unsafe Rust and works just like regular Rust, but gives us extra superpowers. I disagree that “{ X }” and “unsafe { X }” are the same. The former is provably safe if a bug free rust compiler accepts it. The latter leaves the burden of proof on the programmer.
- GolDDranks 6y agoAs you can see, unsafe blocks are required for the assembly block. If you see "unsafe" itself as a problem, you should perhaps read a bit about Rust's philosophy about the matter: https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html