Issue #28317: The disassembler now decodes FORMAT_VALUE argument.
diff --git a/Lib/dis.py b/Lib/dis.py
index 3a706be..0794b7f 100644
--- a/Lib/dis.py
+++ b/Lib/dis.py
@@ -16,6 +16,8 @@
 _have_code = (types.MethodType, types.FunctionType, types.CodeType,
               classmethod, staticmethod, type)
 
+FORMAT_VALUE = opmap['FORMAT_VALUE']
+
 def _try_compile(source, name):
     """Attempts to compile the given source, first as an expression and
        then as a statement if the first approach fails.
@@ -314,6 +316,13 @@
                 argrepr = argval
             elif op in hasfree:
                 argval, argrepr = _get_name_info(arg, cells)
+            elif op == FORMAT_VALUE:
+                argval = ((None, str, repr, ascii)[arg & 0x3], bool(arg & 0x4))
+                argrepr = ('', 'str', 'repr', 'ascii')[arg & 0x3]
+                if argval[1]:
+                    if argrepr:
+                        argrepr += ', '
+                    argrepr += 'with format'
         yield Instruction(opname[op], op,
                           arg, argval, argrepr,
                           offset, starts_line, is_jump_target)
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index f319336..b9b5ac2 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -301,6 +301,27 @@
        TRACEBACK_CODE.co_firstlineno + 4,
        TRACEBACK_CODE.co_firstlineno + 5)
 
+def _fstring(a, b, c, d):
+    return f'{a} {b:4} {c!r} {d!r:4}'
+
+dis_fstring = """\
+%3d           0 LOAD_FAST                0 (a)
+              2 FORMAT_VALUE             0
+              4 LOAD_CONST               1 (' ')
+              6 LOAD_FAST                1 (b)
+              8 LOAD_CONST               2 ('4')
+             10 FORMAT_VALUE             4 (with format)
+             12 LOAD_CONST               1 (' ')
+             14 LOAD_FAST                2 (c)
+             16 FORMAT_VALUE             2 (repr)
+             18 LOAD_CONST               1 (' ')
+             20 LOAD_FAST                3 (d)
+             22 LOAD_CONST               2 ('4')
+             24 FORMAT_VALUE             6 (repr, with format)
+             26 BUILD_STRING             7
+             28 RETURN_VALUE
+""" % (_fstring.__code__.co_firstlineno + 1,)
+
 def _g(x):
     yield x
 
@@ -404,6 +425,9 @@
         gen_disas = self.get_disassembly(_g(1))  # Disassemble generator itself
         self.assertEqual(gen_disas, gen_func_disas)
 
+    def test_disassemble_fstring(self):
+        self.do_disassembly_test(_fstring, dis_fstring)
+
     def test_dis_none(self):
         try:
             del sys.last_traceback
diff --git a/Misc/NEWS b/Misc/NEWS
index 237bf6f..f433959 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -62,6 +62,8 @@
 Library
 -------
 
+- Issue #28317: The disassembler now decodes FORMAT_VALUE argument.
+
 - Issue #26293: Fixed writing ZIP files that starts not from the start of the
   file.  Offsets in ZIP file now are relative to the start of the archive in
   conforming to the specification.