11 ms·
Asmrepl: REPL for x86 Assembly Language
- emersonrsantos 5y agoIt's a modern DOS debug.com
- praveen9920 5y agoI wonder if something like this for wasm. Would be interesting to see something like this in browser
- woodruffw 5y agoMy understanding of wasm (which could be very wrong) is that it's a stack-based virtual machine (like cpython), rather than a load/store or register/memory ISA. You could probably visualize the operand stack and opcode sequence, but it wouldn't be quite as "flashy" as x86's state transitions look when visualized here.
- pavlov 5y agoSomebody should wrap this into a VGA-As-A-Service platform so that kids could learn programming the correct way: mov ax, 13h int 10h
- a-priori 5y agoThe assembly you’ve listed there assumes it runs in real mode and ring 0. You’d need to use virtualization of some kind to execute that.
- StillBored 5y agoWith a BIOS, or CSM on UEFI.
- deleted 5y ago[deleted]
- hoseja 5y agoThat's the only Holy way to run.
- zokier 5y agoDucktaping assembler into DOSBox Debugger would be interesting project, it provides almost whole UI otherwise by itself https://zwomp.com/index.php/2020/05/01/understanding-the-dosbox-debug-screen/ https://zwomp.com/index.php/2020/05/01/understanding-the-dos...
- dcveloper 5y agoI recently found some of my old Pascal mode 13h projects from when I was a teenager. Is DOSBox the best way to run those and Turbo Pascal?
- deleted 5y ago[deleted]
- kingcharles 5y agoI'm guessing you typed that from memory. What were you doing in the 90s? (demo coder, video game developer checking in here)
- enriquto 5y agoThese two lines are deeply ingrained in the minds of a whole generation of programmers. They start a graphics mode of size 320x200 with a 256 byte palette and you can start dumping your pixels in the 0xa0000 segment right away. I am yet to find a modern graphics programming environment that is so comfortable and easy to use as this.
- StillBored 5y agoWell your sorta comparing heavyweight OS graphics stack APIs with old school firmware ones. Even so, things like SDL2 are dead simple, one requests a window region and its possible to write bytes to the resulting buffer that show up in a window. That said modern firmware interfaces are still pretty clean. If you write a UEFI hello world, its possible to access the raw frame buffer with just a connection to the GOP, which is just a couple lines of code in C. Its conceptually pretty close to what your describing, except its designed to work with a slightly more modern programming paradigm. https://wiki.osdev.org/GOP https://wiki.osdev.org/GOP
- enriquto 5y agoI wouldn't call SDL2 "dead simple", unless sarcastically. Just opening an empty SDL window requires writing about 20 lines of code that deal with several different abstractions, a "window", a "surface", a "renderer, an "event". I only want an array of pixels that I can edit and see the results in realtime. It is of course possible to do that, but it seems ridiculously overcomplicated. I was taught as a kid to program simple graphical demos using peek and poke in basic. Then in assembler. In either case, stupid me got colored pixels on the screen after a few minutes of work. Kids these days, how do they start? Please, don't tell me "matplotlib" or I will cry myself to sleep.
- jmmv 5y agoNot exactly the same, but https://www.endbasic.dev/ https://www.endbasic.dev/ tries to achieve precisely that: a REPL with built in graphics for learning purposes, albeit with BASIC instead of asm.
- jonny_eh 5y agoIs this emulating x86? Can I run it on an M1?
- woodruffw 5y agoIt's not emulating x86: it looks like it's assembling instructions on the fly and executing them in a mmap'd region. In other words, it's a very simple JIT. But you probably can run it on an M1 anyways, since Apple's Rosetta will do the dynamic binary translation for you under the hood. YMMV.
- a-dub 5y agowould it? rosetta is a jit translator isn't it? how would it know to translate the instructions that are being generated on the fly interactively? unless there's hardware support in the m1 for translation or some other interrupt that gets triggered to do translation on the fly...
- jsmith45 5y agoI'd assume Rosetta works for newly marked executable pages by not actually flagging them as executable. When control flow attempts to transfer there, a page fault will occur since the page is not actually executable, this is the interrupt that allows Rosetta to step in, see what code was about to be executed, and write out a new ARM equivalent of the code to other memory, and redirect execution to the new equivalent ARM code, before resuming. This basic sort of support is needed for any application that targeting x86 that uses any form of dynamic code generation, which is probably a whole lot more than most people think (even some forms of dynamic linking utilize small amounts of generated code, due to being more efficient than calling a method though a pointer to a pointer to the method).
- a-dub 5y agoso every write to an executable page would have to clear that bit then, triggering an interrupt on jump to let the translator jump in? i'd venture a guess that the rosetta jit stuff probably does some kind of prelinking. kinda makes me wish i had an m1 mac to play with...
- nielsbot 5y agoNot snark, but a serious question: What would one use this for?
- unbanned 5y agoEducation
- woodruffw 5y agoI do a lot of program analysis work, and it's occasionally useful to see the pre- and post-machine states of arbitrary instructions. I have my own (more? less?) hacky version of this program that I use for that purpose; I know other people use GEF and similar GDB extensions for similar purposes.
- qsort 5y agoFor visually exploring the results of applying instructions. Similar to how you would use jshell.
- sebow 5y agoLearning assembly can be a pain, especially without something like gdb (with layout regs &layout asm). This is much simpler and doesn't require you to type like 4-5 extra commands(start gdb, put breakpoint, set layouts, step through the code),thus avoiding the pain that gdb can be for very-simple asm programs.
- tenderlove 5y agoI wrote it because I can never remember what the `test` instruction does to the zero flag. Every time I use the instruction I have to look up the docs. Looking up docs is fine, but running code in a REPL helps me remember things better.
- tzot 5y agoI believe in most (if not all) architectures that have it, a test instruction is the same as comparing to zero; so testing zero sets the zero flag :)
- webdoodle 5y agoI fondly remember writing my first game using assembly that I hand typed from a magazine article on an Amiga. It didn't work because of a reversed peek/poke. It took us all day to figure it out, but we got it working!
- westurner 5y agoThis could be implemented with Jupyter notebooks as a Jupyter kernel or maybe with just fancy use of explicitly returned objects that support the (Ruby-like, implicit) IPython.display.display() magic. IRuby is the Jupyter kernel for Rubylang: iruby/display: https://github.com/SciRuby/iruby/blob/master/lib/iruby/display.rb https://github.com/SciRuby/iruby/blob/master/lib/iruby/displ... iruby/formatter: https://github.com/SciRuby/iruby/blob/master/lib/iruby/formatter.rb https://github.com/SciRuby/iruby/blob/master/lib/iruby/forma... More links to how Jupyter kernels and implicit display() and DAP: Debug Adapter Protocol work: "Evcxr: A Rust REPL and Jupyter Kernel" https://news.ycombinator.com/item?id=25923123 https://news.ycombinator.com/item?id=25923123 "ENH: Mixed Python/C debugging (GDB,)" https://github.com/jupyterlab/debugger/issues/284 https://github.com/jupyterlab/debugger/issues/284 ... "Ask HN: How did you learn x86-64 assembly?" https://news.ycombinator.com/item?id=23930335 https://news.ycombinator.com/item?id=23930335
- kitd 5y agoCool! This reminds me of a fun project I once did, writing an x86 assembler in Lotus 123, using lookup tables. On the odd occasion when it worked, it was immensely fulfilling.
- asimjalis 5y agoNeat. This could be embedded into a Lisp/Clojure syntax.
- User23 5y agoA toy project I have in mind is bootstrapping a lisp in asm and then using lisp macros as assembler macros to build up a high level language that would effectively be native code.
- Jach 5y agoSounds like it'd be cool for the sake of it, but just in case you (or other readers) aren't aware (Edit -- looks like you are very aware ;) SBCL already compiles Lisp code to native code. It's not the same as (asm) macros all the way down, but still. You can even inspect the assembly of a function with the built-in function DISASSEMBLE, and see how it changes with different optimization levels or type declarations or other things. https://pvk.ca/Blog/2014/03/15/sbcl-the-ultimate-assembly-code-breadboard/ https://pvk.ca/Blog/2014/03/15/sbcl-the-ultimate-assembly-co... is worth a read too for a cool experiment in generating custom assembly for a VM idea.
- lispm 5y agoWith various implementations (Clozure Common Lisp) one can write inline assembler interactively.
- fouc 5y agoDoes anyone remember Ketman (1997)? A combination assembler interpreter & tutor for MSDOS. That was the first time I saw a REPL for assembly language. http://web.archive.org/web/20051211022146/http://www.btinternet.com/~btketman/index.html http://web.archive.org/web/20051211022146/http://www.btinter...
- rudolfwinestock 5y agoI've lost the original reference, but Joe Marshall once wrote in comp.lang.lisp: Here's an anecdote I heard once about Minsky. He was showing a student how to use ITS to write a program. ITS was an unusual operating system in that the 'shell' was the DDT debugger. You ran programs by loading them into memory and jumping to the entry point. But you can also just start writing assembly code directly into memory from the DDT prompt. Minsky started with the null program. Obviously, it needs an entry point, so he defined a label for that. He then told the debugger to jump to that label. This immediately raised an error of there being no code at the jump target. So he wrote a few lines of code and restarted the jump instruction. This time it succeeded and the first few instructions were executed. When the debugger again halted, he looked at the register contents and wrote a few more lines. Again proceeding from where he left off he watched the program run the few more instructions. He developed the entire program by 'debugging' the null program.
- userbinator 5y agoMany PC magazines of the late 80s/early 90s had program listings (in Asm) for small utilities that you created by typing them into DEBUG, the very basic debugger that came with DOS. The C64 and ZX ones had similar listings, although I believe they were more commonly in the platform's variant of BASIC. Unfortunately, I don't think this culture existed around Apple's machines since the Macintosh and the Lisa that came before it.
- deckard1 5y agothe way to low-level format early MFM drives was to run DEBUG and enter assembly and call some special routine in the controller chip on the drive. These were instructions that came in the manual with the drive. Pretty wild times. We've come a long way.
- lproven 5y agoDEBUG g=c800:5 From 30-year-old memory. Yes, we actually had to do stuff like this. When I started my first job in the late 1980s, it was normal for hard disks to have a little label with a list of the (known) bad blocks on the drive. (Hand-written by someone at the factory on the first (circa 15-20MB) disks I used; later, on things like big ESDI disks, dot-matrix printed.) In some formatting tools, you had to manually enter them; formats took a long time, so eliminating retries on bad blocks could save half an hour. Novell Netware came with its own low-level formatter called `COMPSURF`: COMPrehensive SURFace analysis. Dozens of people would be sharing a server's hard disk, so data losses would be extra-bad -- and might well bring down the server, losing everyone's work. Note: the assumption in the early days of Novell was that workstations didn't have hard disks of their own and booted off the server too, making a LAN tens of thousands of £/$ cheaper than giving everyone their own HDD. Running COMPSURF before you installed took hours. Server HDDs were big -- hundreds of megabytes! Scanning all that took ages.
- SavantIdiot 5y agoApple //e & ][+ had one built in. It was called the "monitor". You typed "CALL -151" and you started typing assembly code. You could run, save, dump memory and read registers. When I got my first 286 I was surprised I couldn't do the same thing.
- kstrauser 5y agoI had the same (SmartMon) on a C64. I didn't know at the time that it was unusual.
- panzagl 5y agoAt the time, it wasn't...
- Narishma 5y agoYou could do the same thing on your 286. PCs came with DEBUG.COM, which does the same things.
- SavantIdiot 5y agoI didn't know that until about a decade later, unfortunately! People forget that in 1984 information wasn't a click away. The problem with owning a Hong Kong-made 286 clone in 1984, and using pirated software, is that it was extremely hard to learn things. I was limited by the books at my local "Waldenbooks" computer section, which was about 20 books. Computer shopper and Byte magazine were kinda helpful, but I learned very, very slowly. It wasn't until I entered college that I started learning rapidly, but the focus wasn't on PCs (it was still MTS mainframes). It took until my first job writing 16-bit drivers that I finally started learning the nuts and bolts of MSDOS.
- incanus77 5y agoBuilt into the Commodore 128, too.
- Someone 5y ago“Monitor” was a common name for such software (https://en.wikipedia.org/wiki/Machine_code_monitor https://en.wikipedia.org/wiki/Machine_code_monitor) It is a step up from having front-panel switches (https://en.wikipedia.org/wiki/Front_panel https://en.wikipedia.org/wiki/Front_panel) On early mini- and microcomputers, those sometimes had to be used to enter the boot loader (https://en.wikipedia.org/wiki/Booting#Minicomputers https://en.wikipedia.org/wiki/Booting#Minicomputers, https://en.wikipedia.org/wiki/Booting#Booting_the_first_microcomputers https://en.wikipedia.org/wiki/Booting#Booting_the_first_micr...). That was a step down from mainframes, which could automatically read in a program to run at boot. It wouldn’t surprise me much if there were people alive today who still have some muscle memory to rapidly enter such a boot sequence for an Altair.
- master_yoda_1 5y agoIts better to use GCC intrinsic api https://gcc.gnu.org/onlinedocs/gcc-5.3.0/gcc/x86-Built-in-Functions.html#x86-Built-in-Functions https://gcc.gnu.org/onlinedocs/gcc-5.3.0/gcc/x86-Built-in-Fu... It really tough to write x86 assembly.
- NavinF 5y agoDunno how much things have changed, but intrinsics were kinda useless in the past: https://danluu.com/assembly-intrinsics/ https://danluu.com/assembly-intrinsics/
- saagarjha 5y agoUsing intrinsics correctly generally requires understanding assembly, because they are supposed to match the assembly you'd want to generate. Just sprinkling them around because you're not familiar with x86 assembly is unlikely to be productive.
- molticrystal 5y agoThose who enjoy Asmrepl might also enjoy "Cheap EMUlator: lightweight multi-architecture assembly playground" [0] it supports 32 and 64 bit variations of intel, arm, mips and sparc instruction sets and also provides a visual experience and supports many operating systems. If you are on Windows and need something in a console, a nice colorful asm repl is available WinRepl [1] which is similar to " yrp604/rappel (Linux) and Tyilo/asm_repl". [0] https://github.com/hugsy/cemu https://github.com/hugsy/cemu [1] https://github.com/zerosum0x0/WinREPL/ https://github.com/zerosum0x0/WinREPL/
- deepspace 5y agoWow, this brings back memories of my final project for my "programming for Engineering students" course in the mid-80s. I wrote a DOS TSR program (remember those?) which would pop up a window when you pressed a key sequence and present you with an ASM86 REPL. You could selectively 'save' pieces of code, and then when you exited the window, it would paste the saved code as inline assembly code (a hex byte array surrounded by some Turbo Pascal syntax) into your keyboard buffer - the assumption being that you are running the Turbo Pascal IDE, of course. The TSR itself was written in x86 assembly, which added a level of complexity. I would have given and arm and a leg to be able to do it in a high-level language like Ruby.
- djmips 5y agoWhy not Turbo Pascal?
- lproven 5y agoI can only take a guess: that for a TSR on an early DOS PC, you really wanted it to be small. TSRs took a significant chunk of your base memory, and as you only got 640 kB of that, you wanted to save as much as you could. In the later days of DOS, programs grew so big that they wanted all of that 640 kB to themselves. Optional-extra type TSRs went out of fashion and DOS (first DR DOS 5, then MS played copy-cat with MS-DOS 5) gained built-in memory managers to load necessary TSRs (e.g. CD, mouse and keyboard drivers, disk cache, etc.) into Upper Memory Blocks. UMBs were a 386 thing: you used a 386 memory manager to map any unused bits of the I/O space in the PC's memory map (i.e. from 641 kB up to 1 MB) as RAM. Anything that wasn't being used for ROM or memory-mapped I/O, you could put RAM there and then load TSRs into these little chunks of RAM -- 1 or 2 dozen kB of RAM each. https://en.wikipedia.org/wiki/Upper_memory_area https://en.wikipedia.org/wiki/Upper_memory_area Yes, we were that desperate for base memory. It didn't matter if you had 2 or 4 or 16MB of RAM, DOS could only run programs in the 1st 1 MB of it, and only freely use the first ⅓ of that first meg. All the rest could only be used for data, disk caches, and other non-executable stuff. A side-effect of having a 386 memory manager, for real DOS power users, was that fancy 3rd party ones like Quarterdeck QEMM could also offer multitasking. Quarterdeck sold a tool called DESQview that let you run multiple DOS programs side-by-side and switch between them -- radical stuff in the 1980s. But once you had that, you didn't need TSRs any more.